--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omap3530/beagle_drivers/wb/api/src/cyasstorage.c Wed Mar 03 13:10:32 2010 +0000
@@ -0,0 +1,3941 @@
+/* Cypress West Bridge API source file (cyasstorage.c)
+## ===========================
+##
+## Copyright Cypress Semiconductor Corporation, 2006-2009,
+## All Rights Reserved
+## UNPUBLISHED, LICENSED SOFTWARE.
+##
+## CONFIDENTIAL AND PROPRIETARY INFORMATION
+## WHICH IS THE PROPERTY OF CYPRESS.
+##
+## Use of this file is governed
+## by the license agreement included in the file
+##
+## <install>/license/license.txt
+##
+## where <install> is the Cypress software
+## installation root directory path.
+##
+## ===========================
+*/
+
+/*
+* Storage Design
+*
+* The storage module is fairly straight forward once the DMA and LOWLEVEL modules
+* have been designed. The storage module simple takes requests from the user, queues the
+* associated DMA requests for action, and then sends the low level requests to the
+* West Bridge firmware.
+*
+*/
+
+#include "cyashal.h"
+#include "cyasstorage.h"
+#include "cyaserr.h"
+#include "cyasdevice.h"
+#include "cyaslowlevel.h"
+#include "cyasdma.h"
+#include "cyasregs.h"
+
+/* Map a pre-V1.2 media type to the V1.2+ bus number */
+CyAsReturnStatus_t
+CyAnMapBusFromMediaType(CyAsDevice *dev_p, CyAsMediaType type, CyAsBusNumber_t *bus)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t code = (uint8_t)(1 << type) ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+
+ if (dev_p->media_supported[0] & code)
+ {
+ if (dev_p->media_supported[1] & code)
+ {
+ /*
+ * This media type could be supported on multiple buses. So, report
+ * an address resolution error.
+ */
+ ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR ;
+ }
+ else
+ *bus = 0 ;
+ }
+ else
+ {
+ if (dev_p->media_supported[1] & code)
+ *bus = 1 ;
+ else
+ ret = CY_AS_ERROR_NO_SUCH_MEDIA ;
+ }
+
+ return ret ;
+}
+
+static uint16_t
+CreateAddress(CyAsBusNumber_t bus, uint32_t device, uint8_t unit)
+{
+ CyAsHalAssert(bus >= 0 && bus < CY_AS_MAX_BUSES) ;
+ CyAsHalAssert(device < 16) ;
+
+ return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit) ;
+}
+
+CyAsMediaType
+CyAsStorageGetMediaFromAddress(uint16_t v)
+{
+ CyAsMediaType media = CyAsMediaMaxMediaValue ;
+
+ switch(v & 0xFF)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ media = CyAsMediaNand ;
+ break ;
+ case 0x02:
+ media = CyAsMediaSDFlash ;
+ break ;
+ case 0x04:
+ media = CyAsMediaMMCFlash ;
+ break ;
+ case 0x08:
+ media = CyAsMediaCEATA ;
+ break ;
+ case 0x10:
+ media = CyAsMediaSDIO ;
+ break ;
+ default:
+ CyAsHalAssert(0) ;
+ break ;
+ }
+
+ return media ;
+}
+
+CyAsBusNumber_t
+CyAsStorageGetBusFromAddress(uint16_t v)
+{
+ CyAsBusNumber_t bus = (CyAsBusNumber_t)((v >> 12) & 0x0f) ;
+ CyAsHalAssert(bus >= 0 && bus < CY_AS_MAX_BUSES) ;
+ return bus ;
+}
+
+uint32_t
+CyAsStorageGetDeviceFromAddress(uint16_t v)
+{
+ return (uint32_t)((v >> 8) & 0x0f) ;
+}
+
+static uint8_t
+GetUnitFromAddress(uint16_t v)
+{
+ return (uint8_t)(v & 0xff) ;
+}
+
+static CyAsReturnStatus_t
+CyAsMapBadAddr(uint16_t val)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_INVALID_RESPONSE ;
+
+ switch(val)
+ {
+ case 0:
+ ret = CY_AS_ERROR_NO_SUCH_BUS ;
+ break ;
+ case 1:
+ ret = CY_AS_ERROR_NO_SUCH_DEVICE ;
+ break ;
+ case 2:
+ ret = CY_AS_ERROR_NO_SUCH_UNIT ;
+ break ;
+ case 3:
+ ret = CY_AS_ERROR_INVALID_BLOCK ;
+ break ;
+ }
+
+ return ret ;
+}
+
+static void
+MyStorageRequestCallback(CyAsDevice *dev_p, uint8_t context, CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *resp_p, CyAsReturnStatus_t ret)
+{
+ uint16_t val ;
+ uint16_t addr ;
+ CyAsBusNumber_t bus;
+ uint32_t device;
+ CyAsDeviceHandle h = (CyAsDeviceHandle)dev_p ;
+ CyAsDmaEndPoint *ep_p = NULL ;
+
+ (void)resp_p ;
+ (void)context ;
+ (void)ret ;
+
+ switch(CyAsLLRequestResponse_GetCode(req_p))
+ {
+ case CY_RQT_MEDIA_CHANGED:
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+
+ /* Media has either been inserted or removed */
+ addr = CyAsLLRequestResponse_GetWord(req_p, 0) ;
+
+ bus = CyAsStorageGetBusFromAddress(addr);
+ device = CyAsStorageGetDeviceFromAddress(addr);
+
+ /* Clear the entry for this device to force re-query later */
+ CyAsHalMemSet(&(dev_p->storage_device_info[bus][device]), 0,
+ sizeof(dev_p->storage_device_info[bus][device])) ;
+
+ val = CyAsLLRequestResponse_GetWord(req_p, 1) ;
+ if (dev_p->storage_event_cb_ms)
+ {
+ if (val == 1)
+ dev_p->storage_event_cb_ms(h, bus, device, CyAsStorageRemoved, 0) ;
+ else
+ dev_p->storage_event_cb_ms(h, bus, device, CyAsStorageInserted, 0) ;
+ }
+ else if (dev_p->storage_event_cb)
+ {
+ if (val == 1)
+ dev_p->storage_event_cb(h, (CyAsMediaType)bus, CyAsStorageRemoved, 0) ; /*nxz*/
+ else
+ dev_p->storage_event_cb(h, (CyAsMediaType)bus, CyAsStorageInserted, 0) ; /*nxz*/
+ }
+
+ break ;
+
+ case CY_RQT_ANTIOCH_CLAIM:
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ if (dev_p->storage_event_cb || dev_p->storage_event_cb_ms)
+ {
+ val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
+ if (dev_p->storage_event_cb_ms)
+ {
+ if (val & 0x0100)
+ dev_p->storage_event_cb_ms(h, 0, 0, CyAsStorageAntioch, 0) ;
+ if (val & 0x0200)
+ dev_p->storage_event_cb_ms(h, 1, 0, CyAsStorageAntioch, 0) ;
+ }
+ else
+ {
+ if (val & 0x01)
+ dev_p->storage_event_cb(h, CyAsMediaNand, CyAsStorageAntioch, 0) ;
+ if (val & 0x02)
+ dev_p->storage_event_cb(h, CyAsMediaSDFlash, CyAsStorageAntioch, 0) ;
+ if (val & 0x04)
+ dev_p->storage_event_cb(h, CyAsMediaMMCFlash, CyAsStorageAntioch, 0) ;
+ if (val & 0x08)
+ dev_p->storage_event_cb(h, CyAsMediaCEATA, CyAsStorageAntioch, 0) ;
+ }
+ }
+ break ;
+
+ case CY_RQT_ANTIOCH_RELEASE:
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
+ if (dev_p->storage_event_cb_ms)
+ {
+ if (val & 0x0100)
+ dev_p->storage_event_cb_ms(h, 0, 0, CyAsStorageProcessor, 0) ;
+ if (val & 0x0200)
+ dev_p->storage_event_cb_ms(h, 1, 0, CyAsStorageProcessor, 0) ;
+ }
+ else if (dev_p->storage_event_cb)
+ {
+ if (val & 0x01)
+ dev_p->storage_event_cb(h, CyAsMediaNand, CyAsStorageProcessor, 0) ;
+ if (val & 0x02)
+ dev_p->storage_event_cb(h, CyAsMediaSDFlash, CyAsStorageProcessor, 0) ;
+ if (val & 0x04)
+ dev_p->storage_event_cb(h, CyAsMediaMMCFlash, CyAsStorageProcessor, 0) ;
+ if (val & 0x08)
+ dev_p->storage_event_cb(h, CyAsMediaCEATA, CyAsStorageProcessor, 0) ;
+ }
+ break ;
+
+
+ case CY_RQT_SDIO_INTR:
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ val = CyAsLLRequestResponse_GetWord(req_p, 0) ;
+ if (dev_p->storage_event_cb_ms)
+ {
+ if (val & 0x0100)
+ dev_p->storage_event_cb_ms(h, 1, 0, CyAsSdioInterrupt, 0) ;
+ else
+ dev_p->storage_event_cb_ms(h, 0, 0, CyAsSdioInterrupt, 0) ;
+
+ }
+ else if (dev_p->storage_event_cb)
+ {
+ dev_p->storage_event_cb(h, CyAsMediaSDIO, CyAsSdioInterrupt, 0) ;
+ }
+ break;
+
+ case CY_RQT_P2S_DMA_START:
+ /* Do the DMA setup for the waiting operation. This event is used only in
+ * the MTP mode firmware. */
+ CyAsLLSendStatusResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0) ;
+ if (dev_p->storage_oper == CyAsOpRead)
+ {
+ ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_READ_ENDPOINT) ;
+ CyAsDmaEndPointSetStopped(ep_p) ;
+ CyAsDmaKickStart(dev_p, CY_AS_P2S_READ_ENDPOINT) ;
+ }
+ else
+ {
+ ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ;
+ CyAsDmaEndPointSetStopped(ep_p) ;
+ CyAsDmaKickStart(dev_p, CY_AS_P2S_WRITE_ENDPOINT) ;
+ }
+ break ;
+
+ default:
+ CyAsHalPrintMessage("Invalid request received on storage context\n") ;
+ val = req_p->box0 ;
+ CyAsLLSendDataResponse(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, CY_RESP_INVALID_REQUEST, sizeof(val), &val) ;
+ break ;
+ }
+}
+
+static CyAsReturnStatus_t
+IsStorageActive(CyAsDevice *dev_p)
+{
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+ if (dev_p->storage_count == 0)
+ return CY_AS_ERROR_NOT_RUNNING ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+static void
+CyAsStorageFuncCallback(CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t ret) ;
+
+static CyAsReturnStatus_t
+MyHandleResponseNoData(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageStart(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsReturnStatus_t ret)
+{
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ if (dev_p->storage_count > 0 && ret == CY_AS_ERROR_ALREADY_RUNNING)
+ ret = CY_AS_ERROR_SUCCESS ;
+
+ ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CyTrue, CyAsDirectionIn) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ ret = CyAsDmaSetMaxDmaSize(dev_p, CY_AS_P2S_WRITE_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ ret = CyAsDmaEnableEndPoint(dev_p, CY_AS_P2S_READ_ENDPOINT, CyTrue, CyAsDirectionOut) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ ret = CyAsDmaSetMaxDmaSize(dev_p, CY_AS_P2S_READ_ENDPOINT, CY_AS_STORAGE_EP_SIZE) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ CyAsLLRegisterRequestCallback(dev_p, CY_RQT_STORAGE_RQT_CONTEXT, MyStorageRequestCallback) ;
+
+ /* Create the request/response used for storage reads and writes. */
+ dev_p->storage_rw_req_p = CyAsLLCreateRequest(dev_p, 0, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
+ if (dev_p->storage_rw_req_p == 0)
+ {
+ ret = CY_AS_ERROR_OUT_OF_MEMORY;
+ goto destroy;
+ }
+
+ dev_p->storage_rw_resp_p = CyAsLLCreateResponse(dev_p, 5) ;
+ if (dev_p->storage_rw_resp_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
+ ret = CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ /* Increment the storage count only if the above functionality succeeds.*/
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ if (dev_p->storage_count == 0)
+ {
+ CyAsHalMemSet(dev_p->storage_device_info, 0, sizeof(dev_p->storage_device_info)) ;
+ dev_p->is_storage_only_mode = CyFalse ;
+ }
+
+ dev_p->storage_count++ ;
+ }
+
+ CyAsDeviceClearSSSPending(dev_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageStart(CyAsDeviceHandle handle,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if(CyAsDeviceIsSSSPending(dev_p))
+ return CY_AS_ERROR_STARTSTOP_PENDING ;
+
+ CyAsDeviceSetSSSPending(dev_p) ;
+
+ if (dev_p->storage_count == 0)
+ {
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_START_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ {
+ CyAsDeviceClearSSSPending(dev_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsDeviceClearSSSPending(dev_p) ;
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseStorageStart(dev_p, req_p, reply_p, ret) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_START,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ }
+ else
+ {
+ dev_p->storage_count++ ;
+ if (cb)
+ cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0) ;
+ }
+
+ CyAsDeviceClearSSSPending(dev_p) ;
+
+ return ret ;
+}
+
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageStop(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsReturnStatus_t ret)
+{
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
+ CyAsLLDestroyResponse(dev_p, dev_p->storage_rw_resp_p) ;
+ dev_p->storage_count-- ;
+ }
+
+ CyAsDeviceClearSSSPending(dev_p) ;
+
+ return ret ;
+}
+CyAsReturnStatus_t
+CyAsStorageStop(CyAsDeviceHandle handle,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (CyAsDeviceIsStorageAsyncPending(dev_p))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ if(CyAsDeviceIsSSSPending(dev_p))
+ return CY_AS_ERROR_STARTSTOP_PENDING ;
+
+ CyAsDeviceSetSSSPending(dev_p) ;
+
+ if (dev_p->storage_count == 1)
+ {
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_STOP_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 0) ;
+ if (req_p == 0)
+ {
+ CyAsDeviceClearSSSPending(dev_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsDeviceClearSSSPending(dev_p) ;
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseStorageStop(dev_p, req_p, reply_p, ret) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_STOP,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ }
+ else if(dev_p->storage_count > 1)
+ {
+ dev_p->storage_count-- ;
+ if (cb)
+ cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0) ;
+ }
+
+ CyAsDeviceClearSSSPending(dev_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageRegisterCallback(CyAsDeviceHandle handle, CyAsStorageEventCallback callback)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+ if (dev_p->storage_count == 0)
+ return CY_AS_ERROR_NOT_RUNNING ;
+
+ dev_p->storage_event_cb = NULL ;
+ dev_p->storage_event_cb_ms = callback ;
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageClaim(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MEDIA_CLAIMED_RELEASED)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /* The response must be about the address I am trying to claim or the firmware is broken */
+ if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
+ CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))) ||
+ (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
+ CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))))
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetWord(reply_p, 1) != 1)
+ ret = CY_AS_ERROR_NOT_ACQUIRED ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyStorageClaim(CyAsDevice *dev_p,
+ void* data,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint16_t req_flags,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if(dev_p->mtp_count > 0)
+ return CY_AS_ERROR_NOT_VALID_IN_MTP ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_CLAIM_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 4) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseStorageClaim(dev_p, req_p, reply_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_CLAIM,
+ data, dev_p->func_cbs_stor, req_flags,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageClaim(CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ return MyStorageClaim(dev_p, NULL, bus, device, CY_AS_REQUEST_RESPONSE_MS, cb, client) ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageRelease(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_MEDIA_CLAIMED_RELEASED)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /* The response must be about the address I am trying to release or the firmware is broken */
+ if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
+ CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))) ||
+ (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
+ CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0))))
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+
+ if (CyAsLLRequestResponse_GetWord(reply_p, 1) != 0)
+ ret = CY_AS_ERROR_NOT_RELEASED ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyStorageRelease(CyAsDevice* dev_p,
+ void* data,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint16_t req_flags,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if(dev_p->mtp_count > 0)
+ return CY_AS_ERROR_NOT_VALID_IN_MTP ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_RELEASE_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 4) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseStorageRelease(dev_p, req_p, reply_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_RELEASE,
+ data, dev_p->func_cbs_stor, req_flags,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageRelease(CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ return MyStorageRelease(dev_p, NULL, bus, device, CY_AS_REQUEST_RESPONSE_MS, cb, client) ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageQueryBus(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ uint32_t* count)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
+ uint16_t v ;
+
+ if (code == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CY_AS_ERROR_NO_SUCH_BUS ;
+ goto destroy ;
+ }
+
+ if (code != CY_RESP_BUS_DESCRIPTOR)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /*
+ * Verify that the response corresponds to the bus that was queried.
+ */
+ if (CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(req_p, 0)) !=
+ CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)))
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ v = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
+ if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
+ {
+ /*
+ * This request is only for the count of devices on the bus. There
+ * is no need to check the media type.
+ */
+ if (v)
+ *count = 1 ;
+ else
+ *count = 0 ;
+ }
+ else
+ {
+ /*
+ * This request is for the count of devices of a particular type. We need
+ * to check whether the media type found matches the queried type.
+ */
+ CyAsMediaType queried = (CyAsMediaType)CyAsLLRequestResponse_GetWord(req_p, 1) ;
+ CyAsMediaType found = CyAsStorageGetMediaFromAddress(v) ;
+
+ if (queried == found)
+ *count = 1 ;
+ else
+ *count = 0 ;
+ }
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+MyStorageQueryBus(CyAsDevice *dev_p,
+ CyAsBusNumber_t bus,
+ CyAsMediaType type,
+ uint16_t req_flags,
+ uint32_t *count,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret ;
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsFunctCBType cbType = CY_FUNCT_CB_STOR_QUERYBUS ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Create the request to send to the Antioch device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_BUS, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, 0, 0)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)type) ;
+
+ /* Reserve space for the reply, the reply data will not exceed two words. */
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ req_p->flags |= req_flags;
+ return MyHandleResponseStorageQueryBus(dev_p, req_p, reply_p, count) ;
+ }
+ else
+ {
+ if (req_flags == CY_AS_REQUEST_RESPONSE_EX)
+ cbType = CY_FUNCT_CB_STOR_QUERYMEDIA ;
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, cbType,
+ count, dev_p->func_cbs_stor, req_flags,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageQueryBus(CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t *count,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ return MyStorageQueryBus(dev_p, bus, CyAsMediaMaxMediaValue, CY_AS_REQUEST_RESPONSE_MS,
+ count, cb, client) ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageQueryMedia(CyAsDeviceHandle handle,
+ CyAsMediaType type,
+ uint32_t *count,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsBusNumber_t bus ;
+
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ ret = CyAnMapBusFromMediaType(dev_p, type, &bus) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ return MyStorageQueryBus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
+ count, cb, client) ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageQueryDevice(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ void* data_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint16_t v ;
+ CyAsBusNumber_t bus ;
+ CyAsMediaType type ;
+ uint32_t device ;
+ CyBool removable ;
+ CyBool writeable ;
+ CyBool locked ;
+ uint16_t block_size ;
+ uint32_t number_units ;
+ uint32_t number_eus ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_DEVICE_DESCRIPTOR)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /* Unpack the response */
+ v = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ type = CyAsStorageGetMediaFromAddress(v) ;
+ bus = CyAsStorageGetBusFromAddress(v) ;
+ device = CyAsStorageGetDeviceFromAddress(v) ;
+
+ block_size = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
+
+ v = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
+ removable = (v & 0x8000) ? CyTrue : CyFalse ;
+ writeable = (v & 0x0100) ? CyTrue : CyFalse ;
+ locked = (v & 0x0200) ? CyTrue : CyFalse ;
+ number_units = (v & 0xff) ;
+
+ number_eus = (CyAsLLRequestResponse_GetWord(reply_p, 3) << 16) | CyAsLLRequestResponse_GetWord(reply_p, 4) ;
+
+ /* Store the results based on the version of originating function */
+ if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
+ {
+ CyAsStorageQueryDeviceData *store_p = (CyAsStorageQueryDeviceData*)data_p ;
+
+ /* Make sure the response is about the address we asked about - if not, firmware error */
+ if ((bus != store_p->bus) || (device != store_p->device))
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ store_p->desc_p.type = type ;
+ store_p->desc_p.removable = removable ;
+ store_p->desc_p.writeable = writeable ;
+ store_p->desc_p.block_size = block_size ;
+ store_p->desc_p.number_units = number_units ;
+ store_p->desc_p.locked = locked ;
+ store_p->desc_p.erase_unit_size = number_eus ;
+ dev_p->storage_device_info[bus][device] = store_p->desc_p ;
+ }
+ else
+ {
+ CyAsStorageQueryDeviceData_dep *store_p = (CyAsStorageQueryDeviceData_dep*)data_p ;
+
+ /* Make sure the response is about the address we asked about - if not, firmware error */
+ if ((type != store_p->type) || (device != store_p->device))
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ store_p->desc_p.type = type ;
+ store_p->desc_p.removable = removable ;
+ store_p->desc_p.writeable = writeable ;
+ store_p->desc_p.block_size = block_size ;
+ store_p->desc_p.number_units = number_units ;
+ store_p->desc_p.locked = locked ;
+ store_p->desc_p.erase_unit_size = number_eus ;
+ dev_p->storage_device_info[bus][device] = store_p->desc_p ;
+ }
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyStorageQueryDevice(CyAsDevice *dev_p,
+ void* data_p,
+ uint16_t req_flags,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Create the request to send to the Antioch device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
+
+ /* Reserve space for the reply, the reply data will not exceed five words. */
+ reply_p = CyAsLLCreateResponse(dev_p, 5) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ req_p->flags |= req_flags;
+ return MyHandleResponseStorageQueryDevice(dev_p, req_p, reply_p, data_p) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_QUERYDEVICE,
+ data_p, dev_p->func_cbs_stor, req_flags,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageQueryDevice(CyAsDeviceHandle handle,
+ CyAsStorageQueryDeviceData* data_p,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ return MyStorageQueryDevice(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
+ data_p->device, cb, client) ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseStorageQueryUnit(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ void* data_p)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsBusNumber_t bus ;
+ uint32_t device ;
+ uint32_t unit ;
+ CyAsMediaType type ;
+ uint16_t block_size ;
+ uint32_t start_block ;
+ uint32_t unit_size ;
+ uint16_t v ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CyAsMapBadAddr(CyAsLLRequestResponse_GetWord(reply_p, 3)) ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_UNIT_DESCRIPTOR)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /* Unpack the response */
+ v = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ bus = CyAsStorageGetBusFromAddress(v) ;
+ device = CyAsStorageGetDeviceFromAddress(v) ;
+ unit = GetUnitFromAddress(v) ;
+
+ type = CyAsStorageGetMediaFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 1));
+
+ block_size = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
+ start_block = CyAsLLRequestResponse_GetWord(reply_p, 3) | (CyAsLLRequestResponse_GetWord(reply_p, 4) << 16) ;
+ unit_size = CyAsLLRequestResponse_GetWord(reply_p, 5) | (CyAsLLRequestResponse_GetWord(reply_p, 6) << 16) ;
+
+ /* Store the results based on the version of originating function */
+ if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS)
+ {
+ CyAsStorageQueryUnitData *store_p = (CyAsStorageQueryUnitData*)data_p ;
+
+ /* Make sure the response is about the address we asked about - if not, firmware error */
+ if (bus != store_p->bus || device != store_p->device || unit != store_p->unit)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ store_p->desc_p.type = type ;
+ store_p->desc_p.block_size = block_size ;
+ store_p->desc_p.start_block = start_block ;
+ store_p->desc_p.unit_size = unit_size ;
+ }
+ else
+ {
+ CyAsStorageQueryUnitData_dep *store_p = (CyAsStorageQueryUnitData_dep*)data_p ;
+
+ /* Make sure the response is about the media type we asked about - if not, firmware error */
+ if ((type != store_p->type) || (device != store_p->device) || (unit != store_p->unit) ) {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ store_p->desc_p.type = type ;
+ store_p->desc_p.block_size = block_size ;
+ store_p->desc_p.start_block = start_block ;
+ store_p->desc_p.unit_size = unit_size ;
+ }
+
+ dev_p->storage_device_info[bus][device].type = type ;
+ dev_p->storage_device_info[bus][device].block_size = block_size ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyStorageQueryUnit(CyAsDevice *dev_p,
+ void* data_p,
+ uint16_t req_flags,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint32_t unit,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_UNIT, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ if (device > 255)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (unit > 255)
+ return CY_AS_ERROR_NO_SUCH_UNIT ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, (uint8_t)unit)) ;
+
+ /* Reserve space for the reply, the reply data will be of seven words. */
+ reply_p = CyAsLLCreateResponse(dev_p, 7) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ req_p->flags |= req_flags ;
+ return MyHandleResponseStorageQueryUnit(dev_p, req_p, reply_p, data_p) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_QUERYUNIT,
+ data_p, dev_p->func_cbs_stor, req_flags,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageQueryUnit(CyAsDeviceHandle handle,
+ CyAsStorageQueryUnitData* data_p,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ return MyStorageQueryUnit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
+ data_p->device, data_p->unit, cb, client) ;
+}
+
+
+static CyAsReturnStatus_t
+CyAsGetBlockSize(CyAsDevice *dev_p,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsFunctionCallback cb)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 4) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_NO_SUCH_ADDRESS)
+ {
+ ret = CY_AS_ERROR_NO_SUCH_BUS ;
+ goto destroy ;
+ }
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_DEVICE_DESCRIPTOR)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ /* Make sure the response is about the media type we asked about - if not, firmware error */
+ if ((CyAsStorageGetBusFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)) != bus) ||
+ (CyAsStorageGetDeviceFromAddress(CyAsLLRequestResponse_GetWord(reply_p, 0)) != device) )
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+
+ dev_p->storage_device_info[bus][device].block_size = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
+ }
+ else
+ ret = CY_AS_ERROR_INVALID_REQUEST ;
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+MyStorageDeviceControl(
+ CyAsDevice *dev_p,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyBool card_detect_en,
+ CyBool write_prot_en,
+ CyAsStorageCardDetect config_detect,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret ;
+ CyBool use_gpio = CyFalse ;
+
+ (void)device ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (!CyAsDeviceIsConfigured(dev_p))
+ return CY_AS_ERROR_NOT_CONFIGURED ;
+
+ if (!CyAsDeviceIsFirmwareLoaded(dev_p))
+ return CY_AS_ERROR_NO_FIRMWARE ;
+
+ if (CyAsDeviceIsInSuspendMode(dev_p))
+ return CY_AS_ERROR_IN_SUSPEND ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ /* If SD is not supported on the specified bus, then return ERROR */
+ if((dev_p->media_supported[bus] ==0 ) || (dev_p->media_supported[bus] &(1<<CyAsMediaNand)))
+ return CY_AS_ERROR_NOT_SUPPORTED;
+
+ if(config_detect == CyAsStorageDetect_GPIO)
+ use_gpio = CyTrue ;
+ else if(config_detect == CyAsStorageDetect_SDAT_3)
+ use_gpio = CyFalse ;
+ else
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SD_INTERFACE_CONTROL, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, device, 0)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (((uint16_t)card_detect_en << 8) | ((uint16_t)use_gpio << 1) | (uint16_t)write_prot_en)) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ if (CyAsLLRequestResponse_GetCode(reply_p) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ }
+ else
+ {
+
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_DEVICECONTROL,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageDeviceControl(CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyBool card_detect_en,
+ CyBool write_prot_en,
+ CyAsStorageCardDetect config_detect,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ return MyStorageDeviceControl(dev_p, bus, device, card_detect_en, write_prot_en, config_detect, cb, client);
+}
+
+static void
+CyAsAsyncStorageCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t ret)
+{
+ CyAsStorageCallback_dep cb ;
+ CyAsStorageCallback cb_ms ;
+
+ (void)size ;
+ (void)buf_p ;
+ (void)ep ;
+
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+
+ /*
+ * If the LL request callback has already been called, the user
+ * callback has to be called from here.
+ */
+ if (!dev_p->storage_wait)
+ {
+ CyAsHalAssert(dev_p->storage_cb != NULL || dev_p->storage_cb_ms != NULL) ;
+ cb = dev_p->storage_cb ;
+ cb_ms = dev_p->storage_cb_ms ;
+
+ dev_p->storage_cb = 0 ;
+ dev_p->storage_cb_ms = 0 ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ ret = dev_p->storage_error ;
+
+ if (cb_ms)
+ {
+ cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
+ dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
+ }
+ else
+ {
+ cb((CyAsDeviceHandle)dev_p,
+ dev_p->storage_device_info[dev_p->storage_bus_index][dev_p->storage_device_index].type,
+ dev_p->storage_device_index, dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
+ }
+ }
+ else
+ dev_p->storage_error = ret ;
+}
+
+static void
+CyAsAsyncStorageReplyCallback(
+ CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t ret)
+{
+ CyAsStorageCallback_dep cb ;
+ CyAsStorageCallback cb_ms ;
+ uint8_t reqtype ;
+ (void)rqt ;
+ (void)context ;
+
+ reqtype = CyAsLLRequestResponse_GetCode(rqt) ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ if (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_ANTIOCH_DEFERRED_ERROR)
+ {
+ ret = CyAsLLRequestResponse_GetWord(resp, 0) & 0x00FF ;
+ }
+ else if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ }
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ if(reqtype == CY_RQT_READ_BLOCK)
+ CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
+ else
+ CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
+ }
+
+ dev_p->storage_wait = CyFalse ;
+
+ /*
+ * If the DMA callback has already been called, the user callback
+ * has to be called from here.
+ */
+ if (!CyAsDeviceIsStorageAsyncPending(dev_p))
+ {
+ CyAsHalAssert(dev_p->storage_cb != NULL || dev_p->storage_cb_ms != NULL) ;
+ cb = dev_p->storage_cb ;
+ cb_ms = dev_p->storage_cb_ms ;
+
+ dev_p->storage_cb = 0 ;
+ dev_p->storage_cb_ms = 0 ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ ret = dev_p->storage_error ;
+
+ if (cb_ms)
+ {
+ cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
+ dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
+ }
+ else
+ {
+ cb((CyAsDeviceHandle)dev_p,
+ dev_p->storage_device_info[dev_p->storage_bus_index][dev_p->storage_device_index].type,
+ dev_p->storage_device_index, dev_p->storage_unit, dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
+ }
+ }
+ else
+ dev_p->storage_error = ret ;
+}
+
+static CyAsReturnStatus_t
+CyAsStorageAsyncOper(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, uint8_t reqtype, uint16_t req_flags,
+ CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
+ uint32_t block, void *data_p, uint16_t num_blocks,
+ CyAsStorageCallback_dep callback, CyAsStorageCallback callback_ms)
+{
+ uint32_t mask ;
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (unit > 255)
+ return CY_AS_ERROR_NO_SUCH_UNIT ;
+
+ /* We are supposed to return sucess if the number of
+ * blocks is zero
+ */
+ if (num_blocks == 0)
+ {
+ if (callback_ms)
+ callback_ms((CyAsDeviceHandle)dev_p, bus, device, unit, block,
+ ((reqtype == CY_RQT_WRITE_BLOCK) ? CyAsOpWrite : CyAsOpRead),
+ CY_AS_ERROR_SUCCESS) ;
+ else
+ callback((CyAsDeviceHandle)dev_p, dev_p->storage_device_info[bus][device].type,
+ device, unit, block, ((reqtype == CY_RQT_WRITE_BLOCK) ? CyAsOpWrite : CyAsOpRead),
+ CY_AS_ERROR_SUCCESS) ;
+
+ return CY_AS_ERROR_SUCCESS ;
+ }
+
+ if (dev_p->storage_device_info[bus][device].block_size == 0)
+ return CY_AS_ERROR_QUERY_DEVICE_NEEDED ;
+
+ /*
+ * Since async operations can be triggered by interrupt code, we must
+ * insure that we do not get multiple async operations going at one time and
+ * protect this test and set operation from interrupts.
+ * Also need to check for pending Async MTP writes
+ */
+ mask = CyAsHalDisableInterrupts() ;
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait) || (CyAsDeviceIsUsbAsyncPending(dev_p, 6)))
+ {
+ CyAsHalEnableInterrupts(mask) ;
+ return CY_AS_ERROR_ASYNC_PENDING ;
+ }
+
+ CyAsDeviceSetStorageAsyncPending(dev_p) ;
+ CyAsHalEnableInterrupts(mask) ;
+
+ /*
+ * Storage information about the currently outstanding request
+ */
+ dev_p->storage_cb = callback ;
+ dev_p->storage_cb_ms = callback_ms ;
+ dev_p->storage_bus_index = bus ;
+ dev_p->storage_device_index = device ;
+ dev_p->storage_unit = unit ;
+ dev_p->storage_block_addr = block ;
+
+ /* Initialise the request to send to the West Bridge. */
+ req_p = dev_p->storage_rw_req_p ;
+ CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
+
+ /* Initialise the space for reply from the West Bridge. */
+ reply_p = dev_p->storage_rw_resp_p ;
+ CyAsLLInitResponse(reply_p, 5) ;
+
+ /* Remember which version of the API originated the request */
+ req_p->flags |= req_flags ;
+
+ /* Setup the DMA request and adjust the storage operation if we are reading */
+ if (reqtype == CY_RQT_READ_BLOCK)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks,
+ CyFalse, CyTrue, CyAsAsyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpRead ;
+ }
+ else if (reqtype == CY_RQT_WRITE_BLOCK)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks,
+ CyFalse, CyFalse, CyAsAsyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpWrite ;
+ }
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+ return ret ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, (uint8_t)unit)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((block >> 16) & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(block & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_blocks >> 8) & 0x00ff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_blocks << 8) & 0xff00)) ;
+
+ /* Set the burst mode flag. */
+ if (dev_p->is_storage_only_mode)
+ req_p->data[4] |= 0x0001;
+
+ /* Send the request and wait for completion of storage request */
+ dev_p->storage_wait = CyTrue ;
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsAsyncStorageReplyCallback) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+ }
+
+ return ret ;
+}
+
+static void
+CyAsSyncStorageCallback(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, void *buf_p, uint32_t size, CyAsReturnStatus_t err)
+{
+ (void)ep ;
+ (void)buf_p ;
+ (void)size ;
+
+ dev_p->storage_error = err ;
+}
+
+static void
+CyAsSyncStorageReplyCallback(
+ CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t ret)
+{
+ uint8_t reqtype ;
+ (void)rqt ;
+
+ reqtype = CyAsLLRequestResponse_GetCode(rqt) ;
+
+ if (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_ANTIOCH_DEFERRED_ERROR)
+ {
+ ret = CyAsLLRequestResponse_GetWord(resp, 0) & 0x00FF ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ if(reqtype == CY_RQT_READ_BLOCK)
+ CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
+ else
+ CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
+ }
+ }
+ else if (CyAsLLRequestResponse_GetCode(resp) != CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+
+ dev_p->storage_wait = CyFalse ;
+ dev_p->storage_error = ret ;
+
+ /* Wake any threads/processes that are waiting on the read/write completion. */
+ CyAsHalWake (&dev_p->context[context]->channel) ;
+}
+
+static CyAsReturnStatus_t
+CyAsStorageSyncOper(CyAsDevice *dev_p, CyAsEndPointNumber_t ep, uint8_t reqtype, CyAsBusNumber_t bus, uint32_t device,
+ uint32_t unit, uint32_t block, void *data_p, uint16_t num_blocks)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsContext *ctxt_p ;
+ uint32_t loopcount = 200 ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (unit > 255)
+ return CY_AS_ERROR_NO_SUCH_UNIT ;
+
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ /* Also need to check for pending Async MTP writes */
+ if(CyAsDeviceIsUsbAsyncPending(dev_p, 6))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ /* We are supposed to return sucess if the number of
+ * blocks is zero
+ */
+ if (num_blocks == 0)
+ return CY_AS_ERROR_SUCCESS ;
+
+ if (dev_p->storage_device_info[bus][device].block_size == 0)
+ {
+ /*
+ * Normally, a given device has been queried via the query device call before a
+ * read request is issued. Therefore, this normally will not be run.
+ */
+ ret = CyAsGetBlockSize(dev_p, bus, device, 0) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+ }
+
+ /* Initialise the request to send to the West Bridge. */
+ req_p = dev_p->storage_rw_req_p ;
+ CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
+
+ /* Initialise the space for reply from the West Bridge. */
+ reply_p = dev_p->storage_rw_resp_p ;
+ CyAsLLInitResponse(reply_p, 5) ;
+
+ /* Setup the DMA request */
+ if (reqtype == CY_RQT_READ_BLOCK)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks, CyFalse,
+ CyTrue, CyAsSyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpRead ;
+ }
+ else if (reqtype == CY_RQT_WRITE_BLOCK)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, data_p, dev_p->storage_device_info[bus][device].block_size * num_blocks, CyFalse,
+ CyFalse, CyAsSyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpWrite ;
+ }
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, (uint8_t)unit)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((block >> 16) & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(block & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_blocks >> 8) & 0x00ff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_blocks << 8) & 0xff00)) ;
+
+ /* Set the burst mode flag. */
+ if (dev_p->is_storage_only_mode)
+ req_p->data[4] |= 0x0001;
+
+ /* Send the request and wait for completion of storage request */
+ dev_p->storage_wait = CyTrue ;
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSyncStorageReplyCallback) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
+ }
+ else
+ {
+ /* Setup the DMA request */
+ ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
+ ret = CyAsDmaDrainQueue(dev_p, ep, CyFalse) ;
+
+ while (loopcount-- > 0)
+ {
+ if (dev_p->storage_wait == CyFalse)
+ break ;
+ CyAsHalSleepOn(&ctxt_p->channel, 10) ;
+ }
+
+ if (dev_p->storage_wait == CyTrue)
+ {
+ dev_p->storage_wait = CyFalse ;
+ CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
+ ret = CY_AS_ERROR_TIMEOUT ;
+ }
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ ret = dev_p->storage_error ;
+ }
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageRead(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit, uint32_t block,
+ void *data_p, uint16_t num_blocks)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ return CyAsStorageSyncOper(dev_p, dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK, bus, device,
+ unit, block, data_p, num_blocks) ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageWrite(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit, uint32_t block,
+ void *data_p, uint16_t num_blocks)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if(dev_p->mtp_turbo_active)
+ return CY_AS_ERROR_NOT_VALID_DURING_MTP ;
+
+ return CyAsStorageSyncOper(dev_p, dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK, bus, device,
+ unit, block, data_p, num_blocks) ;
+}
+
+
+CyAsReturnStatus_t
+CyAsStorageReadAsync(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
+ uint32_t block, void *data_p, uint16_t num_blocks, CyAsStorageCallback callback)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (callback == 0)
+ return CY_AS_ERROR_NULL_CALLBACK ;
+
+ return CyAsStorageAsyncOper(dev_p, dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK,
+ CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block, data_p, num_blocks, NULL, callback);
+}
+
+CyAsReturnStatus_t
+CyAsStorageWriteAsync(CyAsDeviceHandle handle, CyAsBusNumber_t bus, uint32_t device, uint32_t unit,
+ uint32_t block, void *data_p, uint16_t num_blocks, CyAsStorageCallback callback)
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (callback == 0)
+ return CY_AS_ERROR_NULL_CALLBACK ;
+
+ if(dev_p->mtp_turbo_active)
+ return CY_AS_ERROR_NOT_VALID_DURING_MTP ;
+
+ return CyAsStorageAsyncOper(dev_p, dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK,
+ CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block, data_p, num_blocks, NULL, callback);
+}
+
+
+static void
+MyStorageCancelCallback (
+ CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t stat)
+{
+ (void)context ;
+ (void)stat ;
+
+ /* Nothing to do here, except free up the request and response structures. */
+ CyAsLLDestroyResponse(dev_p, resp) ;
+ CyAsLLDestroyRequest(dev_p, rqt) ;
+}
+
+
+CyAsReturnStatus_t
+CyAsStorageCancelAsync(CyAsDeviceHandle handle)
+{
+ CyAsReturnStatus_t ret ;
+ CyAsLLRequestResponse *req_p , *reply_p ;
+
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (!CyAsDeviceIsStorageAsyncPending(dev_p))
+ return CY_AS_ERROR_ASYNC_NOT_PENDING ;
+
+ /*
+ * Create and send a mailbox request to firmware asking it to abort processing
+ * of the current P2S operation. The rest of the cancel processing will be
+ * driven through the callbacks for the read/write call.
+ */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ABORT_P2S_XFER, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyFalse, MyStorageCancelCallback) ;
+ if (ret)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ }
+
+ return CY_AS_ERROR_SUCCESS ;
+}
+
+/*
+ * This function does all the API side clean-up associated with
+ * CyAsStorageStop, without any communication with the firmware.
+ */
+void CyAsStorageCleanup(CyAsDevice *dev_p)
+{
+ if (dev_p->storage_count)
+ {
+ CyAsLLDestroyRequest(dev_p, dev_p->storage_rw_req_p) ;
+ CyAsLLDestroyResponse(dev_p, dev_p->storage_rw_resp_p) ;
+ dev_p->storage_count = 0 ;
+ CyAsDeviceClearScsiMessages(dev_p) ;
+ CyAsHalMemSet(dev_p->storage_device_info, 0, sizeof(dev_p->storage_device_info)) ;
+
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+ dev_p->storage_cb = 0 ;
+ dev_p->storage_cb_ms = 0 ;
+ dev_p->storage_wait = CyFalse ;
+ }
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseSDRegRead(
+ CyAsDevice *dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsStorageSDRegReadData *info)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t resp_type, i ;
+ uint16_t resp_len ;
+ uint8_t length = info->length ;
+ uint8_t *data_p = info->buf_p ;
+
+ resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;
+ if (resp_type == CY_RESP_SD_REGISTER_DATA)
+ {
+ uint16_t *resp_p = reply_p->data + 1 ;
+ uint16_t temp ;
+
+ resp_len = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ CyAsHalAssert(resp_len >= length) ;
+
+ /*
+ * Copy the values into the output buffer after doing the
+ * necessary bit shifting. The bit shifting is required because
+ * the data comes out of the West Bridge with a 6 bit offset.
+ */
+ i = 0 ;
+ while (length)
+ {
+ temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10)) ;
+ i++ ;
+
+ *data_p++ = (uint8_t)(temp >> 8) ;
+ length-- ;
+
+ if (length)
+ {
+ *data_p++ = (uint8_t)(temp & 0xFF) ;
+ length-- ;
+ }
+ }
+ }
+ else
+ {
+ if (resp_type == CY_RESP_SUCCESS_FAILURE)
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ else
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageSDRegisterRead(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint8_t device,
+ CyAsSDCardRegType regType,
+ CyAsStorageSDRegReadData *data_p,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t length ;
+
+ /*
+ * Sanity checks required before sending the request to the
+ * firmware.
+ */
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (regType > CyAsSDReg_CSD)
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ /* If SD/MMC media is not supported on the addressed bus, return error. */
+ if ((dev_p->media_supported[bus] & (1 << CyAsMediaSDFlash)) == 0)
+ return CY_AS_ERROR_INVALID_PARAMETER ;
+
+ /*
+ * Find the amount of data to be returned. This will be the minimum of
+ * the actual data length, and the length requested.
+ */
+ switch (regType)
+ {
+ case CyAsSDReg_OCR:
+ length = CY_AS_SD_REG_OCR_LENGTH ;
+ break ;
+
+ case CyAsSDReg_CID:
+ length = CY_AS_SD_REG_CID_LENGTH ;
+ break ;
+
+ case CyAsSDReg_CSD:
+ length = CY_AS_SD_REG_CSD_LENGTH ;
+ break ;
+
+ default:
+ length = 0 ;
+ CyAsHalAssert(0) ;
+ }
+
+ if (length < data_p->length)
+ data_p->length = length ;
+ length = data_p->length ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SD_REGISTER_READ, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, (CreateAddress(bus, device, 0) | (uint16_t)regType)) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, CY_AS_SD_REG_MAX_RESP_LENGTH) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ if (cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseSDRegRead(dev_p, req_p, reply_p, data_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_SDREGISTERREAD,
+ data_p, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the MiscFuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageCreatePPartition(
+ CyAsDeviceHandle handle, /* Handle to the device of interest */
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint32_t size, /* of P-port only partition in blocks */
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Partitions cannot be created or deleted while the USB stack is active. */
+ if (dev_p->usb_count)
+ return CY_AS_ERROR_USB_RUNNING ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PARTITION_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
+ if (req_p == 0)
+ {
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00) );
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((size >> 16) & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(size & 0xffff)) ;
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_PARTITION,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageRemovePPartition(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsFunctionCallback cb,
+ uint32_t client)
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Partitions cannot be created or deleted while the USB stack is active. */
+ if (dev_p->usb_count)
+ return CY_AS_ERROR_USB_RUNNING ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_PARTITION_ERASE, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ {
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed one word */
+ reply_p = CyAsLLCreateResponse(dev_p, 1) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00) );
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseNoData(dev_p, req_p, reply_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_NODATA,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static CyAsReturnStatus_t
+MyHandleResponseGetTransferAmount(CyAsDevice* dev_p,
+ CyAsLLRequestResponse *req_p,
+ CyAsLLRequestResponse *reply_p,
+ CyAsMSCProgressData *data)
+{
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t code = CyAsLLRequestResponse_GetCode(reply_p) ;
+ uint16_t v1, v2 ;
+
+ if (code != CY_RESP_TRANSFER_COUNT)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ goto destroy ;
+ }
+
+ v1 = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ v2 = CyAsLLRequestResponse_GetWord(reply_p, 1) ;
+ data->wr_count = (uint32_t)((v1 << 16) | v2) ;
+
+ v1 = CyAsLLRequestResponse_GetWord(reply_p, 2) ;
+ v2 = CyAsLLRequestResponse_GetWord(reply_p, 3) ;
+ data->rd_count = (uint32_t)((v1 << 16) | v2) ;
+
+destroy :
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+CyAsReturnStatus_t
+CyAsStorageGetTransferAmount(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsMSCProgressData *data_p,
+ CyAsFunctionCallback cb,
+ uint32_t client
+ )
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ /* Check if the firmware image supports this feature. */
+ if ((dev_p->media_supported[0]) && (dev_p->media_supported[0] == (1 << CyAsMediaNand)))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_GET_TRANSFER_AMOUNT, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ {
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed four words. */
+ reply_p = CyAsLLCreateResponse(dev_p, 4) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00));
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ return MyHandleResponseGetTransferAmount(dev_p, req_p, reply_p, data_p) ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT,
+ (void *)data_p, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+
+}
+
+CyAsReturnStatus_t
+CyAsStorageErase(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint32_t erase_unit,
+ uint16_t num_erase_units,
+ CyAsFunctionCallback cb,
+ uint32_t client
+ )
+{
+ CyAsLLRequestResponse *req_p, *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ ret = IsStorageActive(dev_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ return ret ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (dev_p->storage_device_info[bus][device].block_size == 0)
+ return CY_AS_ERROR_QUERY_DEVICE_NEEDED ;
+
+ /* If SD is not supported on the specified bus, then return ERROR */
+ if(dev_p->storage_device_info[bus][device].type != CyAsMediaSDFlash)
+ return CY_AS_ERROR_NOT_SUPPORTED;
+
+ if (num_erase_units == 0)
+ return CY_AS_ERROR_SUCCESS ;
+
+ /* Create the request to send to the West Bridge device */
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_ERASE, CY_RQT_STORAGE_RQT_CONTEXT, 5) ;
+ if (req_p == 0)
+ {
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /* Reserve space for the reply, the reply data will not exceed four words. */
+ reply_p = CyAsLLCreateResponse(dev_p, 4) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0x00));
+ CyAsLLRequestResponse_SetWord(req_p, 1, (uint16_t)((erase_unit >> 16) & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, (uint16_t)(erase_unit & 0xffff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 3, (uint16_t)((num_erase_units >> 8) & 0x00ff)) ;
+ CyAsLLRequestResponse_SetWord(req_p, 4, (uint16_t)((num_erase_units << 8) & 0xff00)) ;
+
+ if(cb == 0)
+ {
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ ret = MyHandleResponseNoData(dev_p, req_p, reply_p) ;
+
+ /* If error = "invalid response", this (very likely) means that we are not using the SD-only firmware module
+ which is the only one supporting StorageErase. In this case force a "non supported" error code */
+ if (ret == CY_AS_ERROR_INVALID_RESPONSE)
+ ret = CY_AS_ERROR_NOT_SUPPORTED;
+
+ return ret ;
+ }
+ else
+ {
+ ret = CyAsMiscSendRequest(dev_p, cb, client, CY_FUNCT_CB_STOR_ERASE,
+ 0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
+ req_p, reply_p, CyAsStorageFuncCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /* The request and response are freed as part of the FuncCallback */
+ return ret ;
+ }
+
+destroy:
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+static void
+CyAsStorageFuncCallback(CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t stat)
+{
+ CyAsFuncCBNode* node = (CyAsFuncCBNode*)dev_p->func_cbs_stor->head_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ CyBool exRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX) == CY_AS_REQUEST_RESPONSE_EX ;
+ CyBool msRequest = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS) == CY_AS_REQUEST_RESPONSE_MS ;
+ uint8_t code ;
+ uint8_t cntxt ;
+
+ CyAsHalAssert(exRequest || msRequest) ;
+ CyAsHalAssert(dev_p->func_cbs_stor->count != 0) ;
+ CyAsHalAssert(dev_p->func_cbs_stor->type == CYAS_FUNC_CB) ;
+ (void) exRequest;
+ (void) msRequest;
+
+ (void)context ;
+
+ cntxt = CyAsLLRequestResponse_GetContext(rqt) ;
+ CyAsHalAssert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT) ;
+
+ code = CyAsLLRequestResponse_GetCode(rqt) ;
+ switch(code)
+ {
+ case CY_RQT_START_STORAGE:
+ ret = MyHandleResponseStorageStart(dev_p, rqt, resp, stat) ;
+ break ;
+ case CY_RQT_STOP_STORAGE:
+ ret = MyHandleResponseStorageStop(dev_p, rqt, resp, stat) ;
+ break ;
+ case CY_RQT_CLAIM_STORAGE:
+ ret = MyHandleResponseStorageClaim(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_RELEASE_STORAGE:
+ ret = MyHandleResponseStorageRelease(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_QUERY_MEDIA:
+ CyAsHalAssert(CyFalse) ; /* Not used any more. */
+ break ;
+ case CY_RQT_QUERY_BUS:
+ CyAsHalAssert(node->data != 0) ;
+ ret = MyHandleResponseStorageQueryBus(dev_p, rqt, resp, (uint32_t*)node->data) ;
+ break ;
+ case CY_RQT_QUERY_DEVICE:
+ CyAsHalAssert(node->data != 0) ;
+ ret = MyHandleResponseStorageQueryDevice(dev_p, rqt, resp, node->data) ;
+ break ;
+ case CY_RQT_QUERY_UNIT:
+ CyAsHalAssert(node->data != 0) ;
+ ret = MyHandleResponseStorageQueryUnit(dev_p, rqt, resp, node->data) ;
+ break ;
+ case CY_RQT_SD_INTERFACE_CONTROL:
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_SD_REGISTER_READ:
+ CyAsHalAssert(node->data != 0) ;
+ ret = MyHandleResponseSDRegRead(dev_p, rqt, resp, (CyAsStorageSDRegReadData *)node->data) ;
+ break ;
+ case CY_RQT_PARTITION_STORAGE:
+ ret = MyHandleResponseNoData(dev_p, rqt, resp);
+ break ;
+ case CY_RQT_PARTITION_ERASE:
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+ break ;
+ case CY_RQT_GET_TRANSFER_AMOUNT:
+ CyAsHalAssert(node->data != 0) ;
+ ret = MyHandleResponseGetTransferAmount(dev_p, rqt, resp, (CyAsMSCProgressData *)node->data) ;
+ break ;
+ case CY_RQT_ERASE:
+ ret = MyHandleResponseNoData(dev_p, rqt, resp) ;
+
+ /* If error = "invalid response", this (very likely) means that we are not using the SD-only firmware module
+ which is the only one supporting StorageErase. In this case force a "non supported" error code */
+ if (ret == CY_AS_ERROR_INVALID_RESPONSE)
+ ret = CY_AS_ERROR_NOT_SUPPORTED;
+
+ break ;
+
+ default:
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ CyAsHalAssert(CyFalse) ;
+ break ;
+ }
+
+ /*
+ * If the low level layer returns a direct error, use the corresponding error code.
+ * If not, use the error code based on the response from firmware.
+ */
+ if (stat == CY_AS_ERROR_SUCCESS)
+ stat = ret ;
+
+ /* Call the user callback, if there is one */
+ if (node->cb_p)
+ node->cb_p((CyAsDeviceHandle)dev_p, stat, node->client_data, (CyAsFunctCBType)node->dataType, node->data) ;
+ CyAsRemoveCBNode(dev_p->func_cbs_stor) ;
+}
+
+
+static void
+CyAsSdioSyncReplyCallback(
+ CyAsDevice *dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse *rqt,
+ CyAsLLRequestResponse *resp,
+ CyAsReturnStatus_t ret)
+{
+ (void)rqt ;
+
+ if ((CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_GET_TUPLE )||
+ (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_EXT))
+ {
+ ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
+ if ((ret & 0x00FF) != CY_AS_ERROR_SUCCESS)
+ {
+ if(CyAsLLRequestResponse_GetCode(rqt) == CY_RQT_SDIO_READ_EXTENDED)
+ CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
+ else
+ CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
+ }
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+
+ dev_p->storage_rw_resp_p=resp;
+ dev_p->storage_wait = CyFalse ;
+ if(((ret & 0x00FF) == CY_AS_ERROR_IO_ABORTED) || ((ret & 0x00FF) == CY_AS_ERROR_IO_SUSPENDED))
+ dev_p->storage_error = (ret & 0x00FF);
+ else
+ dev_p->storage_error = (ret & 0x00FF)? CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS ;
+
+ /* Wake any threads/processes that are waiting on the read/write completion. */
+ CyAsHalWake (&dev_p->context[context]->channel);
+}
+
+CyAsReturnStatus_t
+CyAsSdioDeviceCheck(
+ CyAsDevice* dev_p,
+ CyAsBusNumber_t bus,
+ uint32_t device)
+{
+ if (!dev_p ||(dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
+ return CY_AS_ERROR_INVALID_HANDLE ;
+
+ if (bus < 0 || bus >= CY_AS_MAX_BUSES)
+ return CY_AS_ERROR_NO_SUCH_BUS ;
+
+ if (device >= CY_AS_MAX_STORAGE_DEVICES)
+ return CY_AS_ERROR_NO_SUCH_DEVICE ;
+
+ if (!CyAsDeviceIsAstoriaDev(dev_p))
+ return CY_AS_ERROR_NOT_SUPPORTED ;
+
+ return (IsStorageActive(dev_p)) ;
+}
+
+CyAsReturnStatus_t
+CyAsSdioDirectIo(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t isWrite,
+ uint8_t * data_p )
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint16_t resp_data;
+
+ /*
+ * Sanity checks required before sending the request to the
+ * firmware.
+ */
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_FUNCTION_SUSPENDED;
+
+ req_p = CyAsLLCreateRequest(dev_p, (isWrite==CyTrue)?CY_RQT_SDIO_WRITE_DIRECT:CY_RQT_SDIO_READ_DIRECT,
+ CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /*Setting up request*/
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;
+ /* D1 */
+ if(isWrite==CyTrue)
+ {
+ CyAsLLRequestResponse_SetWord(req_p, 1, ((argument<<8)|0x0080|(nFunctionNo<<4)|
+ ((miscBuf&CY_SDIO_RAW)<<3)|((miscBuf&CY_SDIO_REARM_INT)>>5)|(uint16_t)(address>>15)));
+ }
+ else
+ {
+ CyAsLLRequestResponse_SetWord(req_p, 1, (nFunctionNo<<4)|((miscBuf&CY_SDIO_REARM_INT)>>5)|
+ (uint16_t)(address>>15));
+ }
+ /* D2 */
+ CyAsLLRequestResponse_SetWord(req_p, 2, ((uint16_t)((address&0x00007fff)<<1))) ;
+
+ /*Create response*/
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ /*Sending the request*/
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ /*Check reply type*/
+ if ( CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SDIO_DIRECT)
+ {
+ resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ if(resp_data>>8)
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ else if (data_p!=0)
+ *(uint8_t*)(data_p)=(uint8_t)(resp_data&0x00ff);
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+
+destroy:
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsSdioDirectRead(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint8_t * data_p)
+{
+ return (CyAsSdioDirectIo(handle,bus,device, nFunctionNo, address, miscBuf, 0x00, CyFalse, data_p));
+}
+
+CyAsReturnStatus_t
+CyAsSdioDirectWrite(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t * data_p)
+{
+ return (CyAsSdioDirectIo(handle,bus,device, nFunctionNo, address, miscBuf, argument, CyTrue, data_p));
+}
+
+/*Cmd53 IO*/
+CyAsReturnStatus_t
+CyAsSdioExtendedIO(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t isWrite,
+ uint8_t * data_p ,
+ uint8_t isResume)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t resp_type;
+ uint8_t reqtype;
+ uint16_t resp_data;
+ CyAsContext *ctxt_p ;
+ uint32_t dmasize,loopcount = 200;
+ CyAsEndPointNumber_t ep;
+
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_FUNCTION_SUSPENDED;
+
+
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+ /* Request for 0 bytes of blocks is returned as a success*/
+ if(argument == 0)
+ return CY_AS_ERROR_SUCCESS;
+
+ /* Initialise the request to send to the West Bridge device. */
+ if(isWrite == CyTrue)
+ {
+ reqtype =CY_RQT_SDIO_WRITE_EXTENDED;
+ ep=dev_p->storage_write_endpoint;
+ }
+ else
+ {
+ reqtype=CY_RQT_SDIO_READ_EXTENDED;
+ ep=dev_p->storage_read_endpoint;
+ }
+
+ req_p = dev_p->storage_rw_req_p ;
+ CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
+
+ /* Initialise the space for reply from the Antioch. */
+ reply_p = dev_p->storage_rw_resp_p ;
+ CyAsLLInitResponse(reply_p, 2) ;
+
+ /* Setup the DMA request */
+ if(!(miscBuf&CY_SDIO_BLOCKMODE))
+ {
+ if(argument > dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize)
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+
+ }
+ else
+ {
+ if( argument > 511)
+ {
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+ }
+ }
+
+ if(argument == 512)
+ argument =0;
+
+ dmasize=((miscBuf&CY_SDIO_BLOCKMODE) !=0)? dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize*argument:argument;
+
+ ret = CyAsDmaQueueRequest(dev_p, ep, (void*)(data_p), dmasize, CyFalse,
+ (isWrite & CyTrue)?CyFalse:CyTrue, CyAsSyncStorageCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo|((isResume)?0x80:0x00) )) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, ((uint16_t)nFunctionNo)<<12|
+ ((uint16_t)(miscBuf&(CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))<<9|
+ (uint16_t)(address>>7)|((isWrite==CyTrue)?0x8000:0x0000 )) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, ((uint16_t)(address&0x0000ffff)<<9) | argument) ;
+
+
+ /* Send the request and wait for completion of storage request */
+ dev_p->storage_wait = CyTrue ;
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioSyncReplyCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
+ }
+ else
+ {
+ /* Setup the DMA request */
+ ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
+ ret = CyAsDmaDrainQueue(dev_p, ep, CyTrue) ;
+
+ while (loopcount-- > 0)
+ {
+ if (dev_p->storage_wait == CyFalse)
+ break;
+ CyAsHalSleepOn(&ctxt_p->channel, 10) ;
+ }
+ if (dev_p->storage_wait == CyTrue)
+ {
+ dev_p->storage_wait = CyFalse ;
+ CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
+ dev_p->storage_error = CY_AS_ERROR_TIMEOUT ;
+ }
+
+ ret=dev_p->storage_error;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+
+
+ resp_type = CyAsLLRequestResponse_GetCode(dev_p->storage_rw_resp_p) ;
+ if (resp_type == CY_RESP_SDIO_EXT)
+ {
+ resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0)&0x00ff ;
+ if(resp_data)
+ {
+ ret = CY_AS_ERROR_INVALID_REQUEST ;
+ }
+
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ }
+ return ret;
+
+}
+
+static void
+CyAsSdioAsyncReplyCallback(
+ CyAsDevice* dev_p,
+ uint8_t context,
+ CyAsLLRequestResponse* rqt,
+ CyAsLLRequestResponse* resp,
+ CyAsReturnStatus_t ret )
+{
+ CyAsStorageCallback cb_ms ;
+ uint8_t reqtype ;
+ uint32_t pendingblocks;
+ (void)rqt ;
+ (void)context ;
+
+ pendingblocks = 0;
+ reqtype = CyAsLLRequestResponse_GetCode(rqt) ;
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ if ((CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SUCCESS_FAILURE) ||
+ (CyAsLLRequestResponse_GetCode(resp) == CY_RESP_SDIO_EXT))
+ {
+ ret = CyAsLLRequestResponse_GetWord(resp, 0) ;
+ ret &= 0x00FF ;
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ }
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ if(reqtype == CY_RQT_SDIO_READ_EXTENDED)
+ CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, ret) ;
+ else
+ CyAsDmaCancel(dev_p, dev_p->storage_write_endpoint, ret) ;
+
+ dev_p->storage_error = ret;
+ }
+
+
+
+ dev_p->storage_wait = CyFalse ;
+
+ /*
+ * If the DMA callback has already been called, the user callback
+ * has to be called from here.
+ */
+ if (!CyAsDeviceIsStorageAsyncPending(dev_p))
+ {
+ CyAsHalAssert(dev_p->storage_cb_ms != NULL) ;
+ cb_ms = dev_p->storage_cb_ms ;
+
+ dev_p->storage_cb = 0 ;
+ dev_p->storage_cb_ms = 0 ;
+
+ if ((ret == CY_AS_ERROR_SUCCESS) || (ret == CY_AS_ERROR_IO_ABORTED) || (ret == CY_AS_ERROR_IO_SUSPENDED))
+ {
+ ret = dev_p->storage_error ;
+ pendingblocks = ((uint32_t)CyAsLLRequestResponse_GetWord(resp, 1))<<16;
+ }
+ else
+ ret = CY_AS_ERROR_INVALID_RESPONSE;
+
+ cb_ms((CyAsDeviceHandle)dev_p, dev_p->storage_bus_index, dev_p->storage_device_index,
+ (dev_p->storage_unit | pendingblocks), dev_p->storage_block_addr, dev_p->storage_oper, ret) ;
+ }
+ else
+ dev_p->storage_error = ret ;
+}
+
+
+CyAsReturnStatus_t
+CyAsSdioExtendedIOAsync(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t isWrite,
+ uint8_t * data_p,
+ CyAsStorageCallback callback )
+{
+
+ uint32_t mask ;
+ uint32_t dmasize;
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ uint8_t reqtype;
+ CyAsEndPointNumber_t ep;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_FUNCTION_SUSPENDED;
+
+ if (callback == 0)
+ return CY_AS_ERROR_NULL_CALLBACK ;
+
+ /* We are supposed to return sucess if the number of
+ * blocks is zero
+ */
+ if(((miscBuf&CY_SDIO_BLOCKMODE)!=0)&&(argument==0))
+ {
+ callback(handle, bus, device,nFunctionNo,address,((isWrite) ? CyAsOpWrite : CyAsOpRead), CY_AS_ERROR_SUCCESS) ;
+ return CY_AS_ERROR_SUCCESS ;
+ }
+
+
+ /*
+ * Since async operations can be triggered by interrupt code, we must
+ * insure that we do not get multiple async operations going at one time and
+ * protect this test and set operation from interrupts.
+ */
+ mask = CyAsHalDisableInterrupts() ;
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+ {
+ CyAsHalEnableInterrupts(mask) ;
+ return CY_AS_ERROR_ASYNC_PENDING ;
+ }
+ CyAsDeviceSetStorageAsyncPending(dev_p) ;
+ CyAsHalEnableInterrupts(mask) ;
+
+
+ /*
+ * Storage information about the currently outstanding request
+ */
+ dev_p->storage_cb_ms = callback ;
+ dev_p->storage_bus_index = bus ;
+ dev_p->storage_device_index = device ;
+ dev_p->storage_unit = nFunctionNo ;
+ dev_p->storage_block_addr = address ;
+
+ if(isWrite == CyTrue)
+ {
+ reqtype =CY_RQT_SDIO_WRITE_EXTENDED;
+ ep=dev_p->storage_write_endpoint;
+ }
+ else
+ {
+ reqtype=CY_RQT_SDIO_READ_EXTENDED;
+ ep=dev_p->storage_read_endpoint;
+ }
+
+ /* Initialise the request to send to the West Bridge. */
+ req_p = dev_p->storage_rw_req_p ;
+ CyAsLLInitRequest(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3) ;
+
+ /* Initialise the space for reply from the West Bridge. */
+ reply_p = dev_p->storage_rw_resp_p ;
+ CyAsLLInitResponse(reply_p, 2) ;
+
+ if(!(miscBuf&CY_SDIO_BLOCKMODE))
+ {
+ if(argument > dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize)
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+
+ }
+ else
+ {
+ if( argument > 511)
+ {
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+ }
+ }
+
+ if(argument == 512)
+ argument =0;
+ dmasize=((miscBuf&CY_SDIO_BLOCKMODE) !=0)? dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize*argument:argument;
+
+ /* Setup the DMA request and adjust the storage operation if we are reading */
+ if (reqtype == CY_RQT_SDIO_READ_EXTENDED)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, (void*)data_p,dmasize , CyFalse, CyTrue,CyAsAsyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpRead ;
+ }
+ else if (reqtype == CY_RQT_SDIO_WRITE_EXTENDED)
+ {
+ ret = CyAsDmaQueueRequest(dev_p, ep, (void*)data_p, dmasize, CyFalse, CyFalse,CyAsAsyncStorageCallback) ;
+ dev_p->storage_oper = CyAsOpWrite ;
+ }
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+ return ret ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;
+ CyAsLLRequestResponse_SetWord(req_p, 1, ((uint16_t)nFunctionNo)<<12|
+ ((uint16_t)(miscBuf&(CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))<<9|
+ (uint16_t)(address>>7)|((isWrite==CyTrue)?0x8000:0x0000 )) ;
+ CyAsLLRequestResponse_SetWord(req_p, 2, ((uint16_t)(address&0x0000ffff)<<9) | argument) ;
+
+
+ /* Send the request and wait for completion of storage request */
+ dev_p->storage_wait = CyTrue ;
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioAsyncReplyCallback) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDmaCancel(dev_p, ep, CY_AS_ERROR_CANCELED) ;
+ CyAsDeviceClearStorageAsyncPending(dev_p) ;
+ }
+ else
+ {
+ CyAsDmaKickStart(dev_p, ep) ;
+ }
+
+ return ret ;
+}
+
+/* CMD53 Extended Read*/
+CyAsReturnStatus_t
+CyAsSdioExtendedRead(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t * data_p,
+ CyAsSdioCallback callback )
+{
+ if (callback==0)
+ return CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyFalse,data_p,0);
+
+ return CyAsSdioExtendedIOAsync(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyFalse,data_p,callback);
+}
+
+/* CMD53 Extended Write*/
+CyAsReturnStatus_t
+CyAsSdioExtendedWrite(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint32_t address,
+ uint8_t miscBuf,
+ uint16_t argument,
+ uint8_t * data_p,
+ CyAsSdioCallback callback )
+{
+ if (callback==0)
+ return CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyTrue,data_p,0);
+
+ return CyAsSdioExtendedIOAsync(handle,bus,device,nFunctionNo,address,miscBuf,argument,CyTrue,data_p,callback);
+}
+
+
+/* Read the CIS info tuples for the given function and Tuple ID*/
+CyAsReturnStatus_t
+CyAsSdioGetCISInfo(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint16_t tupleId,
+ uint8_t * data_p )
+{
+
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint16_t resp_data;
+ CyAsContext *ctxt_p ;
+ uint32_t loopcount = 200;
+
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!( CyAsSdioCheckFunctionInitialized(handle,bus,0) ))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+ return CY_AS_ERROR_ASYNC_PENDING ;
+
+
+ /* Initialise the request to send to the Antioch. */
+ req_p = dev_p->storage_rw_req_p ;
+ CyAsLLInitRequest(req_p, CY_RQT_SDIO_GET_TUPLE, CY_RQT_STORAGE_RQT_CONTEXT, 2) ;
+
+ /* Initialise the space for reply from the Antioch. */
+ reply_p = dev_p->storage_rw_resp_p ;
+ CyAsLLInitResponse(reply_p, 3) ;
+
+ /* Setup the DMA request */
+ ret = CyAsDmaQueueRequest(dev_p, dev_p->storage_read_endpoint, data_p+1, 255, CyFalse, CyTrue,
+ CyAsSyncStorageCallback) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;
+
+ /* Set tuple id to fetch. */
+ CyAsLLRequestResponse_SetWord(req_p, 1, tupleId<<8) ;
+
+ /* Send the request and wait for completion of storage request */
+ dev_p->storage_wait = CyTrue ;
+ ret = CyAsLLSendRequest(dev_p, req_p, reply_p, CyTrue, CyAsSdioSyncReplyCallback) ;
+
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ CyAsDmaCancel(dev_p, dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED) ;
+ }
+ else
+ {
+ /* Setup the DMA request */
+ ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT] ;
+ ret = CyAsDmaDrainQueue(dev_p, dev_p->storage_read_endpoint, CyTrue) ;
+
+ while (loopcount-- > 0)
+ {
+ if (dev_p->storage_wait == CyFalse)
+ break;
+ CyAsHalSleepOn(&ctxt_p->channel, 10) ;
+ }
+
+ if (dev_p->storage_wait == CyTrue)
+ {
+ dev_p->storage_wait = CyFalse ;
+ CyAsLLRemoveRequest(dev_p, ctxt_p, req_p, CyTrue) ;
+ return CY_AS_ERROR_TIMEOUT ;
+ }
+ ret = dev_p->storage_error ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ {
+ return ret ;
+ }
+
+ if ( CyAsLLRequestResponse_GetCode(dev_p->storage_rw_resp_p) == CY_RESP_SDIO_GET_TUPLE)
+ {
+ resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ if(resp_data)
+ {
+ ret = CY_AS_ERROR_INVALID_REQUEST ;
+ }
+ else if (data_p!=0)
+ *(uint8_t*)data_p=(uint8_t)(CyAsLLRequestResponse_GetWord(reply_p, 0)&0x00ff);
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+ }
+ return ret;
+}
+
+/*Query Device*/
+CyAsReturnStatus_t
+CyAsSdioQueryCard(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ CyAsSDIOCard* data_p )
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+
+ uint8_t resp_type;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ /* Allocating memory to the SDIO device structure in dev_p */
+
+ CyAsHalMemSet(& dev_p->sdiocard[bus],0,sizeof(CyAsSDIODevice));
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_QUERY_CARD, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0 )) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 5) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ resp_type = CyAsLLRequestResponse_GetCode(reply_p);
+ if ( resp_type == CY_RESP_SDIO_QUERY_CARD)
+ {
+ dev_p->sdiocard[bus].card.num_functions = (uint8_t)((reply_p->data[0]&0xff00)>>8);
+ dev_p->sdiocard[bus].card.memory_present = (uint8_t)reply_p->data[0]&0x0001;
+ dev_p->sdiocard[bus].card.manufacturer_Id = reply_p->data[1];
+ dev_p->sdiocard[bus].card.manufacturer_info = reply_p->data[2];
+ dev_p->sdiocard[bus].card.blocksize = reply_p->data[3];
+ dev_p->sdiocard[bus].card.maxblocksize = reply_p->data[3];
+ dev_p->sdiocard[bus].card.card_capability = (uint8_t)((reply_p->data[4]&0xff00)>>8);
+ dev_p->sdiocard[bus].card.sdio_version = (uint8_t)(reply_p->data[4]&0x00ff);
+ dev_p->sdiocard[bus].function_init_map = 0x01;
+ data_p->num_functions = dev_p->sdiocard[bus].card.num_functions;
+ data_p->memory_present = dev_p->sdiocard[bus].card.memory_present;
+ data_p->manufacturer_Id = dev_p->sdiocard[bus].card.manufacturer_Id;
+ data_p->manufacturer_info = dev_p->sdiocard[bus].card.manufacturer_info;
+ data_p->blocksize = dev_p->sdiocard[bus].card.blocksize;
+ data_p->maxblocksize = dev_p->sdiocard[bus].card.maxblocksize;
+ data_p->card_capability = dev_p->sdiocard[bus].card.card_capability;
+ data_p->sdio_version = dev_p->sdiocard[bus].card.sdio_version;
+ }
+ else
+ {
+ if (resp_type == CY_RESP_SUCCESS_FAILURE)
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ else
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+destroy:
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+/*Reset SDIO card. */
+CyAsReturnStatus_t
+CyAsSdioResetCard(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device )
+{
+
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t resp_type;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(dev_p->sdiocard != 0)
+ {
+ dev_p->sdiocard[bus].function_init_map=0;
+ dev_p->sdiocard[bus].function_suspended_map = 0;
+ }
+
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_RESET_DEV, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /*Setup mailbox */
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, 0) ) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+
+ resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;
+
+
+ if (resp_type == CY_RESP_SUCCESS_FAILURE)
+ {
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ if(ret == CY_AS_ERROR_SUCCESS)
+ {
+ ret = CyAsSdioQueryCard(handle,bus,device,0);
+ }
+ }
+ else
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+
+destroy:
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+/* Initialise an IO function*/
+CyAsReturnStatus_t
+CyAsSdioInitFunction(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint8_t miscBuf )
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t resp_type;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,0)))
+ return CY_AS_ERROR_NOT_RUNNING;
+
+ if((CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ {
+ if(miscBuf&CY_SDIO_FORCE_INIT)
+ dev_p->sdiocard[bus].function_init_map&=(~(1<<nFunctionNo));
+ else
+ return CY_AS_ERROR_ALREADY_RUNNING;
+ }
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo )) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 5) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;
+
+ if (resp_type == CY_RESP_SDIO_INIT_FUNCTION)
+ {
+
+ dev_p->sdiocard[bus].function[nFunctionNo-1].function_code = (uint8_t)((reply_p->data[0]&0xff00)>>8);
+ dev_p->sdiocard[bus].function[nFunctionNo-1].extended_func_code = (uint8_t)reply_p->data[0]&0x00ff;
+ dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize = reply_p->data[1];
+ dev_p->sdiocard[bus].function[nFunctionNo-1].maxblocksize = reply_p->data[1];
+ dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn = (uint32_t)(reply_p->data[2])<<16;
+ dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn |=(uint32_t)(reply_p->data[3]);
+ dev_p->sdiocard[bus].function[nFunctionNo-1].csa_bits = (uint8_t)((reply_p->data[4]&0xff00)>>8);
+ dev_p->sdiocard[bus].function[nFunctionNo-1].wakeup_support = (uint8_t)(reply_p->data[4]&0x0001);
+ dev_p->sdiocard[bus].function_init_map |= (1<<nFunctionNo);
+ CyAsSdioClearFunctionSuspended(handle,bus,nFunctionNo);
+
+ }
+ else
+ {
+ if (resp_type == CY_RESP_SUCCESS_FAILURE)
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ else
+ ret = CY_AS_ERROR_INVALID_FUNCTION ;
+ }
+
+destroy:
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+/*Query individual functions. */
+CyAsReturnStatus_t
+CyAsSdioQueryFunction(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ CyAsSDIOFunc* data_p )
+{
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ CyAsReturnStatus_t ret;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ data_p->blocksize = dev_p->sdiocard[bus].function[nFunctionNo-1].blocksize;
+ data_p->card_psn = dev_p->sdiocard[bus].function[nFunctionNo-1].card_psn;
+ data_p->csa_bits = dev_p->sdiocard[bus].function[nFunctionNo-1].csa_bits;
+ data_p->extended_func_code = dev_p->sdiocard[bus].function[nFunctionNo-1].extended_func_code;
+ data_p->function_code = dev_p->sdiocard[bus].function[nFunctionNo-1].function_code;
+ data_p->maxblocksize = dev_p->sdiocard[bus].function[nFunctionNo-1].maxblocksize;
+ data_p->wakeup_support = dev_p->sdiocard[bus].function[nFunctionNo-1].wakeup_support;
+
+
+ return CY_AS_ERROR_SUCCESS;
+}
+
+/* Abort the Current Extended IO Operation*/
+CyAsReturnStatus_t
+CyAsSdioAbortFunction(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ uint8_t resp_type;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ if ((CyAsDeviceIsStorageAsyncPending(dev_p)) || (dev_p->storage_wait))
+ {
+ if(!(CyAsSdioGetCardCapability(handle,bus) & CY_SDIO_SDC ))
+ {
+ return CY_AS_ERROR_INVALID_COMMAND;
+ }
+ }
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_ABORT_IO, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /*Setup mailbox */
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+ resp_type = CyAsLLRequestResponse_GetCode(reply_p) ;
+
+ if (resp_type == CY_RESP_SUCCESS_FAILURE)
+ ret = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ else
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+
+
+destroy:
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+}
+
+/* Suspend IO to current function*/
+CyAsReturnStatus_t
+CyAsSdioSuspend(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo)
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(!(CyAsSdioCheckSupportBusSuspend(handle,bus)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(!(CyAsSdioGetCardCapability(handle,bus) & CY_SDIO_SDC))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_FUNCTION_SUSPENDED;
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /*Setup mailbox */
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+
+ if (ret == CY_AS_ERROR_SUCCESS)
+ {
+ ret = CyAsLLRequestResponse_GetCode(reply_p) ;
+ CyAsSdioSetFunctionSuspended(handle,bus,nFunctionNo);
+ }
+
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+
+ return ret ;
+}
+
+/*Resume suspended function*/
+CyAsReturnStatus_t
+CyAsSdioResume(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ CyAsOperType op,
+ uint8_t miscBuf,
+ uint16_t pendingblockcount,
+ uint8_t *data_p
+ )
+{
+ CyAsLLRequestResponse *req_p , *reply_p ;
+ CyAsReturnStatus_t resp_data, ret = CY_AS_ERROR_SUCCESS ;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ /* If suspend resume is not supported return */
+ if(!(CyAsSdioCheckSupportBusSuspend(handle,bus)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ /* if the function is not suspended return. */
+ if(!(CyAsSdioCheckFunctionSuspended(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ req_p = CyAsLLCreateRequest(dev_p, CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1) ;
+ if (req_p == 0)
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+
+ /*Setup mailbox */
+ CyAsLLRequestResponse_SetWord(req_p, 0, CreateAddress(bus, (uint8_t)device, nFunctionNo) ) ;
+
+ reply_p = CyAsLLCreateResponse(dev_p, 2) ;
+ if (reply_p == 0)
+ {
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ return CY_AS_ERROR_OUT_OF_MEMORY ;
+ }
+ ret = CyAsLLSendRequestWaitReply(dev_p, req_p, reply_p) ;
+
+ if (ret != CY_AS_ERROR_SUCCESS)
+ goto destroy ;
+
+
+ if ( CyAsLLRequestResponse_GetCode(reply_p) == CY_RESP_SDIO_RESUME)
+ {
+ resp_data = CyAsLLRequestResponse_GetWord(reply_p, 0) ;
+ if(resp_data & 0x00ff)
+ {
+ /* Send extended read request to resume the read. */
+ if(op == CyAsOpRead)
+ {
+ ret = CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,0,miscBuf,pendingblockcount,CyFalse,data_p,1);
+ }
+ else
+ {
+ ret = CyAsSdioExtendedIO(handle,bus,device,nFunctionNo,0,miscBuf,pendingblockcount,CyTrue,data_p,1);
+ }
+ }
+ else
+ {
+ ret= CY_AS_ERROR_SUCCESS;
+ }
+
+ }
+ else
+ {
+ ret = CY_AS_ERROR_INVALID_RESPONSE ;
+ }
+
+destroy:
+ CyAsSdioClearFunctionSuspended(handle,bus,nFunctionNo);
+ if(req_p!=0)
+ CyAsLLDestroyRequest(dev_p, req_p) ;
+ if(reply_p!=0)
+ CyAsLLDestroyResponse(dev_p, reply_p) ;
+ return ret ;
+
+}
+
+/*Set function blocksize. Size cannot exceed max block size for the function*/
+CyAsReturnStatus_t
+CyAsSdioSetBlocksize(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo,
+ uint16_t blocksize)
+{
+ CyAsReturnStatus_t ret;
+ CyAsDevice *dev_p = (CyAsDevice *)handle ;
+ ret = CyAsSdioDeviceCheck(dev_p,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_INVALID_FUNCTION;
+ if( nFunctionNo == 0)
+ {
+ if ( blocksize > CyAsSdioGetCardMaxBlocksize(handle,bus))
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+ else if (blocksize == CyAsSdioGetCardBlocksize(handle,bus))
+ return CY_AS_ERROR_SUCCESS;
+ }
+ else
+ {
+ if ( blocksize > CyAsSdioGetFunctionMaxBlocksize(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_INVALID_BLOCKSIZE;
+ else if (blocksize == CyAsSdioGetFunctionBlocksize(handle,bus,nFunctionNo))
+ return CY_AS_ERROR_SUCCESS;
+ }
+
+ ret = CyAsSdioDirectWrite(handle,bus,device,0,(uint16_t)(nFunctionNo<<8)|0x10,0,blocksize&0x00ff,0);
+ if(ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+ ret = CyAsSdioDirectWrite(handle,bus,device,0,(uint16_t)(nFunctionNo<<8)|0x11,0,(blocksize&0xff00)>>8,0);
+ if (ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(nFunctionNo ==0)
+ CyAsSdioSetCardBlockSize(handle,bus,blocksize);
+ else
+ CyAsSdioSetFunctionBlockSize(handle,bus,nFunctionNo,blocksize);
+ return ret;
+}
+
+/* Deinitialize an SDIO function*/
+CyAsReturnStatus_t
+CyAsSdioDeInitFunction(
+ CyAsDeviceHandle handle,
+ CyAsBusNumber_t bus,
+ uint32_t device,
+ uint8_t nFunctionNo)
+{
+ CyAsReturnStatus_t ret;
+ uint8_t temp;
+
+ if(nFunctionNo == 0)
+ return CY_AS_ERROR_INVALID_FUNCTION;
+
+ ret = CyAsSdioDeviceCheck((CyAsDevice*)handle,bus,device);
+ if( ret != CY_AS_ERROR_SUCCESS )
+ return ret;
+
+ if(!(CyAsSdioCheckFunctionInitialized(handle,bus,nFunctionNo)))
+ return CY_AS_ERROR_SUCCESS;
+
+ temp =(uint8_t)(((CyAsDevice*)handle)->sdiocard[bus].function_init_map & (~(1<<nFunctionNo)));
+ CyAsSdioDirectWrite(handle,bus,device,0,0x02,0,temp,0);
+ ((CyAsDevice*)handle)->sdiocard[bus].function_init_map &= (~(1<<nFunctionNo));
+
+ return CY_AS_ERROR_SUCCESS;
+}
+
+/* This includes the implementation of the deprecated functions for backward
+ * compatibility
+ */
+#include "cyasstorage_dep_impl.h"
+
+/*[]*/