linux/drivers/staging/westbridge/astoria/api/src/cyasstorage.c
<<
>>
Prefs
   1/* Cypress West Bridge API source file (cyasstorage.c)
   2## ===========================
   3## Copyright (C) 2010  Cypress Semiconductor
   4##
   5## This program is free software; you can redistribute it and/or
   6## modify it under the terms of the GNU General Public License
   7## as published by the Free Software Foundation; either version 2
   8## of the License, or (at your option) any later version.
   9##
  10## This program is distributed in the hope that it will be useful,
  11## but WITHOUT ANY WARRANTY; without even the implied warranty of
  12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13## GNU General Public License for more details.
  14##
  15## You should have received a copy of the GNU General Public License
  16## along with this program; if not, write to the Free Software
  17## Foundation, Inc., 51 Franklin Street, Fifth Floor
  18## Boston, MA  02110-1301, USA.
  19## ===========================
  20*/
  21
  22/*
  23* Storage Design
  24*
  25* The storage module is fairly straight forward once the
  26* DMA and LOWLEVEL modules have been designed.  The
  27* storage module simple takes requests from the user, queues
  28* the associated DMA requests for action, and then sends
  29* the low level requests to the West Bridge firmware.
  30*
  31*/
  32
  33#include "../../include/linux/westbridge/cyashal.h"
  34#include "../../include/linux/westbridge/cyasstorage.h"
  35#include "../../include/linux/westbridge/cyaserr.h"
  36#include "../../include/linux/westbridge/cyasdevice.h"
  37#include "../../include/linux/westbridge/cyaslowlevel.h"
  38#include "../../include/linux/westbridge/cyasdma.h"
  39#include "../../include/linux/westbridge/cyasregs.h"
  40
  41/* Map a pre-V1.2 media type to the V1.2+ bus number */
  42cy_as_return_status_t
  43cy_an_map_bus_from_media_type(cy_as_device *dev_p,
  44        cy_as_media_type type, cy_as_bus_number_t *bus)
  45{
  46        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
  47        uint8_t code = (uint8_t)(1 << type);
  48        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
  49                return CY_AS_ERROR_INVALID_HANDLE;
  50
  51        if (!cy_as_device_is_configured(dev_p))
  52                return CY_AS_ERROR_NOT_CONFIGURED;
  53
  54        if (!cy_as_device_is_firmware_loaded(dev_p))
  55                return CY_AS_ERROR_NO_FIRMWARE;
  56
  57
  58        if (dev_p->media_supported[0] & code) {
  59                if (dev_p->media_supported[1] & code) {
  60                        /*
  61                         * this media type could be supported on multiple
  62                         * buses. so, report an address resolution error.
  63                         */
  64                        ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR;
  65                } else
  66                        *bus = 0;
  67        } else {
  68                if (dev_p->media_supported[1] & code)
  69                        *bus = 1;
  70                else
  71                        ret = CY_AS_ERROR_NO_SUCH_MEDIA;
  72        }
  73
  74        return ret;
  75}
  76
  77static uint16_t
  78create_address(cy_as_bus_number_t bus, uint32_t device, uint8_t unit)
  79{
  80        cy_as_hal_assert(bus >= 0  && bus < CY_AS_MAX_BUSES);
  81        cy_as_hal_assert(device < 16);
  82
  83        return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit);
  84}
  85
  86cy_as_media_type
  87cy_as_storage_get_media_from_address(uint16_t v)
  88{
  89        cy_as_media_type media = cy_as_media_max_media_value;
  90
  91        switch (v & 0xFF) {
  92        case 0x00:
  93                break;
  94        case 0x01:
  95                media = cy_as_media_nand;
  96                break;
  97        case 0x02:
  98                media = cy_as_media_sd_flash;
  99                break;
 100        case 0x04:
 101                media = cy_as_media_mmc_flash;
 102                break;
 103        case 0x08:
 104                media = cy_as_media_ce_ata;
 105                break;
 106        case 0x10:
 107                media = cy_as_media_sdio;
 108                break;
 109        default:
 110                cy_as_hal_assert(0);
 111                        break;
 112        }
 113
 114        return media;
 115}
 116
 117cy_as_bus_number_t
 118cy_as_storage_get_bus_from_address(uint16_t v)
 119{
 120        cy_as_bus_number_t bus = (cy_as_bus_number_t)((v >> 12) & 0x0f);
 121        cy_as_hal_assert(bus >= 0 && bus < CY_AS_MAX_BUSES);
 122        return bus;
 123}
 124
 125uint32_t
 126cy_as_storage_get_device_from_address(uint16_t v)
 127{
 128        return (uint32_t)((v >> 8) & 0x0f);
 129}
 130
 131static uint8_t
 132get_unit_from_address(uint16_t v)
 133{
 134        return (uint8_t)(v & 0xff);
 135}
 136
 137static cy_as_return_status_t
 138cy_as_map_bad_addr(uint16_t val)
 139{
 140        cy_as_return_status_t ret = CY_AS_ERROR_INVALID_RESPONSE;
 141
 142        switch (val) {
 143        case 0:
 144                ret = CY_AS_ERROR_NO_SUCH_BUS;
 145                break;
 146        case 1:
 147                ret = CY_AS_ERROR_NO_SUCH_DEVICE;
 148                break;
 149        case 2:
 150                ret = CY_AS_ERROR_NO_SUCH_UNIT;
 151                break;
 152        case 3:
 153                ret = CY_AS_ERROR_INVALID_BLOCK;
 154                break;
 155        }
 156
 157        return ret;
 158}
 159
 160static void
 161my_storage_request_callback(cy_as_device *dev_p,
 162                uint8_t context,
 163                cy_as_ll_request_response *req_p,
 164                cy_as_ll_request_response *resp_p,
 165                cy_as_return_status_t ret)
 166{
 167        uint16_t val;
 168        uint16_t addr;
 169        cy_as_bus_number_t bus;
 170        uint32_t device;
 171        cy_as_device_handle h = (cy_as_device_handle)dev_p;
 172        cy_as_dma_end_point *ep_p = NULL;
 173
 174        (void)resp_p;
 175        (void)context;
 176        (void)ret;
 177
 178        switch (cy_as_ll_request_response__get_code(req_p)) {
 179        case CY_RQT_MEDIA_CHANGED:
 180                cy_as_ll_send_status_response(dev_p,
 181                        CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
 182
 183                /* Media has either been inserted or removed */
 184                addr = cy_as_ll_request_response__get_word(req_p, 0);
 185
 186                bus = cy_as_storage_get_bus_from_address(addr);
 187                device = cy_as_storage_get_device_from_address(addr);
 188
 189                /* Clear the entry for this device to force re-query later */
 190                cy_as_hal_mem_set(&(dev_p->storage_device_info[bus][device]), 0,
 191                        sizeof(dev_p->storage_device_info[bus][device]));
 192
 193                val = cy_as_ll_request_response__get_word(req_p, 1);
 194                if (dev_p->storage_event_cb_ms) {
 195                        if (val == 1)
 196                                dev_p->storage_event_cb_ms(h, bus,
 197                                        device, cy_as_storage_removed, 0);
 198                        else
 199                                dev_p->storage_event_cb_ms(h, bus,
 200                                        device, cy_as_storage_inserted, 0);
 201                } else if (dev_p->storage_event_cb) {
 202                        if (val == 1)
 203                                dev_p->storage_event_cb(h, bus,
 204                                        cy_as_storage_removed, 0);
 205                        else
 206                                dev_p->storage_event_cb(h, bus,
 207                                        cy_as_storage_inserted, 0);
 208                }
 209
 210                break;
 211
 212        case CY_RQT_ANTIOCH_CLAIM:
 213                cy_as_ll_send_status_response(dev_p,
 214                        CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
 215                if (dev_p->storage_event_cb || dev_p->storage_event_cb_ms) {
 216                        val = cy_as_ll_request_response__get_word(req_p, 0);
 217                        if (dev_p->storage_event_cb_ms) {
 218                                if (val & 0x0100)
 219                                        dev_p->storage_event_cb_ms(h, 0, 0,
 220                                                cy_as_storage_antioch, 0);
 221                                if (val & 0x0200)
 222                                        dev_p->storage_event_cb_ms(h, 1, 0,
 223                                                cy_as_storage_antioch, 0);
 224                        } else {
 225                                if (val & 0x01)
 226                                        dev_p->storage_event_cb(h,
 227                                                cy_as_media_nand,
 228                                                cy_as_storage_antioch, 0);
 229                                if (val & 0x02)
 230                                        dev_p->storage_event_cb(h,
 231                                                cy_as_media_sd_flash,
 232                                                cy_as_storage_antioch, 0);
 233                                if (val & 0x04)
 234                                        dev_p->storage_event_cb(h,
 235                                                cy_as_media_mmc_flash,
 236                                                cy_as_storage_antioch, 0);
 237                                if (val & 0x08)
 238                                        dev_p->storage_event_cb(h,
 239                                                cy_as_media_ce_ata,
 240                                                cy_as_storage_antioch, 0);
 241                        }
 242                }
 243                break;
 244
 245        case CY_RQT_ANTIOCH_RELEASE:
 246                cy_as_ll_send_status_response(dev_p,
 247                        CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
 248                val = cy_as_ll_request_response__get_word(req_p, 0);
 249                if (dev_p->storage_event_cb_ms) {
 250                        if (val & 0x0100)
 251                                dev_p->storage_event_cb_ms(h, 0, 0,
 252                                        cy_as_storage_processor, 0);
 253                        if (val & 0x0200)
 254                                dev_p->storage_event_cb_ms(h, 1, 0,
 255                                        cy_as_storage_processor, 0);
 256                } else if (dev_p->storage_event_cb) {
 257                        if (val & 0x01)
 258                                dev_p->storage_event_cb(h,
 259                                        cy_as_media_nand,
 260                                        cy_as_storage_processor, 0);
 261                        if (val & 0x02)
 262                                dev_p->storage_event_cb(h,
 263                                        cy_as_media_sd_flash,
 264                                        cy_as_storage_processor, 0);
 265                        if (val & 0x04)
 266                                dev_p->storage_event_cb(h,
 267                                        cy_as_media_mmc_flash,
 268                                        cy_as_storage_processor, 0);
 269                        if (val & 0x08)
 270                                dev_p->storage_event_cb(h,
 271                                        cy_as_media_ce_ata,
 272                                        cy_as_storage_processor, 0);
 273                }
 274                break;
 275
 276
 277        case CY_RQT_SDIO_INTR:
 278                cy_as_ll_send_status_response(dev_p,
 279                        CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
 280                val = cy_as_ll_request_response__get_word(req_p, 0);
 281                if (dev_p->storage_event_cb_ms) {
 282                        if (val & 0x0100)
 283                                dev_p->storage_event_cb_ms(h, 1, 0,
 284                                        cy_as_sdio_interrupt, 0);
 285                        else
 286                                dev_p->storage_event_cb_ms(h, 0, 0,
 287                                        cy_as_sdio_interrupt, 0);
 288
 289                } else if (dev_p->storage_event_cb) {
 290                        dev_p->storage_event_cb(h,
 291                                cy_as_media_sdio, cy_as_sdio_interrupt, 0);
 292                }
 293                break;
 294
 295        case CY_RQT_P2S_DMA_START:
 296                /* Do the DMA setup for the waiting operation. */
 297                cy_as_ll_send_status_response(dev_p,
 298                        CY_RQT_STORAGE_RQT_CONTEXT, CY_AS_ERROR_SUCCESS, 0);
 299                cy_as_device_set_p2s_dma_start_recvd(dev_p);
 300                if (dev_p->storage_oper == cy_as_op_read) {
 301                        ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_READ_ENDPOINT);
 302                        cy_as_dma_end_point_set_stopped(ep_p);
 303                        cy_as_dma_kick_start(dev_p, CY_AS_P2S_READ_ENDPOINT);
 304                } else {
 305                        ep_p = CY_AS_NUM_EP(dev_p, CY_AS_P2S_WRITE_ENDPOINT);
 306                        cy_as_dma_end_point_set_stopped(ep_p);
 307                        cy_as_dma_kick_start(dev_p, CY_AS_P2S_WRITE_ENDPOINT);
 308                }
 309                break;
 310
 311        default:
 312                cy_as_hal_print_message("invalid request received "
 313                        "on storage context\n");
 314                val = req_p->box0;
 315                cy_as_ll_send_data_response(dev_p, CY_RQT_STORAGE_RQT_CONTEXT,
 316                        CY_RESP_INVALID_REQUEST, sizeof(val), &val);
 317                break;
 318        }
 319}
 320
 321static cy_as_return_status_t
 322is_storage_active(cy_as_device *dev_p)
 323{
 324        if (!cy_as_device_is_configured(dev_p))
 325                return CY_AS_ERROR_NOT_CONFIGURED;
 326
 327        if (!cy_as_device_is_firmware_loaded(dev_p))
 328                return CY_AS_ERROR_NO_FIRMWARE;
 329
 330        if (dev_p->storage_count == 0)
 331                return CY_AS_ERROR_NOT_RUNNING;
 332
 333        if (cy_as_device_is_in_suspend_mode(dev_p))
 334                return CY_AS_ERROR_IN_SUSPEND;
 335
 336        return CY_AS_ERROR_SUCCESS;
 337}
 338
 339static void
 340cy_as_storage_func_callback(cy_as_device *dev_p,
 341                                        uint8_t context,
 342                                        cy_as_ll_request_response *rqt,
 343                                        cy_as_ll_request_response *resp,
 344                                        cy_as_return_status_t ret);
 345
 346static cy_as_return_status_t
 347my_handle_response_no_data(cy_as_device *dev_p,
 348                                cy_as_ll_request_response *req_p,
 349                                cy_as_ll_request_response *reply_p)
 350{
 351        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 352
 353        if (cy_as_ll_request_response__get_code(reply_p) !=
 354                CY_RESP_SUCCESS_FAILURE) {
 355                ret = CY_AS_ERROR_INVALID_RESPONSE;
 356                goto destroy;
 357        }
 358
 359        ret = cy_as_ll_request_response__get_word(reply_p, 0);
 360
 361destroy:
 362        cy_as_ll_destroy_request(dev_p, req_p);
 363        cy_as_ll_destroy_response(dev_p, reply_p);
 364
 365        return ret;
 366}
 367
 368static cy_as_return_status_t
 369my_handle_response_storage_start(cy_as_device *dev_p,
 370                        cy_as_ll_request_response *req_p,
 371                        cy_as_ll_request_response *reply_p,
 372                        cy_as_return_status_t ret)
 373{
 374        if (ret != CY_AS_ERROR_SUCCESS)
 375                goto destroy;
 376
 377        if (cy_as_ll_request_response__get_code(reply_p) !=
 378                CY_RESP_SUCCESS_FAILURE) {
 379                ret = CY_AS_ERROR_INVALID_RESPONSE;
 380                goto destroy;
 381        }
 382
 383        ret = cy_as_ll_request_response__get_word(reply_p, 0);
 384        if (dev_p->storage_count > 0 && ret ==
 385        CY_AS_ERROR_ALREADY_RUNNING)
 386                ret = CY_AS_ERROR_SUCCESS;
 387
 388        ret = cy_as_dma_enable_end_point(dev_p,
 389                CY_AS_P2S_WRITE_ENDPOINT, cy_true, cy_as_direction_in);
 390        if (ret != CY_AS_ERROR_SUCCESS)
 391                goto destroy;
 392
 393        ret = cy_as_dma_set_max_dma_size(dev_p,
 394                CY_AS_P2S_WRITE_ENDPOINT, CY_AS_STORAGE_EP_SIZE);
 395        if (ret != CY_AS_ERROR_SUCCESS)
 396                goto destroy;
 397
 398        ret = cy_as_dma_enable_end_point(dev_p,
 399                CY_AS_P2S_READ_ENDPOINT, cy_true, cy_as_direction_out);
 400        if (ret != CY_AS_ERROR_SUCCESS)
 401                goto destroy;
 402
 403        ret = cy_as_dma_set_max_dma_size(dev_p,
 404                CY_AS_P2S_READ_ENDPOINT, CY_AS_STORAGE_EP_SIZE);
 405        if (ret != CY_AS_ERROR_SUCCESS)
 406                goto destroy;
 407
 408        cy_as_ll_register_request_callback(dev_p,
 409                CY_RQT_STORAGE_RQT_CONTEXT, my_storage_request_callback);
 410
 411        /* Create the request/response used for storage reads and writes. */
 412        dev_p->storage_rw_req_p  = cy_as_ll_create_request(dev_p,
 413                0, CY_RQT_STORAGE_RQT_CONTEXT, 5);
 414        if (dev_p->storage_rw_req_p == 0) {
 415                ret = CY_AS_ERROR_OUT_OF_MEMORY;
 416                goto destroy;
 417        }
 418
 419        dev_p->storage_rw_resp_p = cy_as_ll_create_response(dev_p, 5);
 420        if (dev_p->storage_rw_resp_p == 0) {
 421                cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
 422                ret = CY_AS_ERROR_OUT_OF_MEMORY;
 423        }
 424
 425destroy:
 426        cy_as_ll_destroy_request(dev_p, req_p);
 427        cy_as_ll_destroy_response(dev_p, reply_p);
 428
 429        /* Increment the storage count only if
 430         * the above functionality succeeds.*/
 431        if (ret == CY_AS_ERROR_SUCCESS) {
 432                if (dev_p->storage_count == 0) {
 433                        cy_as_hal_mem_set(dev_p->storage_device_info,
 434                                0, sizeof(dev_p->storage_device_info));
 435                        dev_p->is_storage_only_mode = cy_false;
 436                }
 437
 438                dev_p->storage_count++;
 439        }
 440
 441        cy_as_device_clear_s_s_s_pending(dev_p);
 442
 443        return ret;
 444}
 445
 446cy_as_return_status_t
 447cy_as_storage_start(cy_as_device_handle handle,
 448                                   cy_as_function_callback cb,
 449                                   uint32_t client)
 450{
 451        cy_as_ll_request_response *req_p, *reply_p;
 452        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 453        cy_as_device *dev_p = (cy_as_device *)handle;
 454
 455        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 456                return CY_AS_ERROR_INVALID_HANDLE;
 457
 458        if (!cy_as_device_is_configured(dev_p))
 459                return CY_AS_ERROR_NOT_CONFIGURED;
 460
 461        if (!cy_as_device_is_firmware_loaded(dev_p))
 462                return CY_AS_ERROR_NO_FIRMWARE;
 463
 464        if (cy_as_device_is_in_suspend_mode(dev_p))
 465                return CY_AS_ERROR_IN_SUSPEND;
 466
 467        if (cy_as_device_is_s_s_s_pending(dev_p))
 468                return CY_AS_ERROR_STARTSTOP_PENDING;
 469
 470        cy_as_device_set_s_s_s_pending(dev_p);
 471
 472        if (dev_p->storage_count == 0) {
 473                /* Create the request to send to the West Bridge device */
 474                req_p = cy_as_ll_create_request(dev_p,
 475                        CY_RQT_START_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
 476                if (req_p == 0) {
 477                        cy_as_device_clear_s_s_s_pending(dev_p);
 478                        return CY_AS_ERROR_OUT_OF_MEMORY;
 479                }
 480
 481                /* Reserve space for the reply, the reply data
 482                 * will not exceed one word */
 483                reply_p = cy_as_ll_create_response(dev_p, 1);
 484                if (reply_p == 0) {
 485                        cy_as_device_clear_s_s_s_pending(dev_p);
 486                        cy_as_ll_destroy_request(dev_p, req_p);
 487                        return CY_AS_ERROR_OUT_OF_MEMORY;
 488                }
 489
 490                if (cb == 0) {
 491                        ret = cy_as_ll_send_request_wait_reply(dev_p,
 492                                req_p, reply_p);
 493                        if (ret != CY_AS_ERROR_SUCCESS)
 494                                goto destroy;
 495
 496                        return my_handle_response_storage_start(dev_p,
 497                                req_p, reply_p, ret);
 498                } else {
 499                        ret = cy_as_misc_send_request(dev_p, cb, client,
 500                                CY_FUNCT_CB_STOR_START, 0, dev_p->func_cbs_stor,
 501                                CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
 502                                cy_as_storage_func_callback);
 503
 504                        if (ret != CY_AS_ERROR_SUCCESS)
 505                                goto destroy;
 506
 507                        /* The request and response are freed as
 508                         * part of the FuncCallback */
 509                        return ret;
 510                }
 511
 512destroy:
 513                cy_as_ll_destroy_request(dev_p, req_p);
 514                cy_as_ll_destroy_response(dev_p, reply_p);
 515        } else {
 516                dev_p->storage_count++;
 517                if (cb)
 518                        cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0);
 519        }
 520
 521        cy_as_device_clear_s_s_s_pending(dev_p);
 522
 523        return ret;
 524}
 525
 526
 527static cy_as_return_status_t
 528my_handle_response_storage_stop(cy_as_device *dev_p,
 529                                cy_as_ll_request_response *req_p,
 530                                cy_as_ll_request_response *reply_p,
 531                                cy_as_return_status_t ret)
 532{
 533        if (ret != CY_AS_ERROR_SUCCESS)
 534                goto destroy;
 535
 536        if (cy_as_ll_request_response__get_code(reply_p) !=
 537                CY_RESP_SUCCESS_FAILURE) {
 538                ret = CY_AS_ERROR_INVALID_RESPONSE;
 539                goto destroy;
 540        }
 541
 542destroy:
 543        cy_as_ll_destroy_request(dev_p, req_p);
 544        cy_as_ll_destroy_response(dev_p, reply_p);
 545
 546        if (ret == CY_AS_ERROR_SUCCESS) {
 547                cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
 548                cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p);
 549                dev_p->storage_count--;
 550        }
 551
 552        cy_as_device_clear_s_s_s_pending(dev_p);
 553
 554        return ret;
 555}
 556cy_as_return_status_t
 557cy_as_storage_stop(cy_as_device_handle handle,
 558                                  cy_as_function_callback cb,
 559                                  uint32_t client)
 560{
 561        cy_as_ll_request_response *req_p , *reply_p;
 562        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 563
 564        cy_as_device *dev_p = (cy_as_device *)handle;
 565
 566        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 567                return CY_AS_ERROR_INVALID_HANDLE;
 568
 569        ret = is_storage_active(dev_p);
 570        if (ret != CY_AS_ERROR_SUCCESS)
 571                return ret;
 572
 573        if (cy_as_device_is_storage_async_pending(dev_p))
 574                return CY_AS_ERROR_ASYNC_PENDING;
 575
 576        if (cy_as_device_is_s_s_s_pending(dev_p))
 577                return CY_AS_ERROR_STARTSTOP_PENDING;
 578
 579        cy_as_device_set_s_s_s_pending(dev_p);
 580
 581        if (dev_p->storage_count == 1) {
 582
 583                /* Create the request to send to the West Bridge device */
 584                req_p = cy_as_ll_create_request(dev_p,
 585                        CY_RQT_STOP_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 0);
 586                if (req_p == 0) {
 587                        cy_as_device_clear_s_s_s_pending(dev_p);
 588                        return CY_AS_ERROR_OUT_OF_MEMORY;
 589                }
 590
 591                /* Reserve space for the reply, the reply data
 592                 * will not exceed one word */
 593                reply_p = cy_as_ll_create_response(dev_p, 1);
 594                if (reply_p == 0) {
 595                        cy_as_device_clear_s_s_s_pending(dev_p);
 596                        cy_as_ll_destroy_request(dev_p, req_p);
 597                        return CY_AS_ERROR_OUT_OF_MEMORY;
 598                }
 599
 600                if (cb == 0) {
 601                        ret = cy_as_ll_send_request_wait_reply(dev_p,
 602                                req_p, reply_p);
 603                        if (ret != CY_AS_ERROR_SUCCESS)
 604                                goto destroy;
 605
 606                        return my_handle_response_storage_stop(dev_p,
 607                                req_p, reply_p, ret);
 608                } else {
 609                        ret = cy_as_misc_send_request(dev_p, cb, client,
 610                                CY_FUNCT_CB_STOR_STOP, 0, dev_p->func_cbs_stor,
 611                                CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
 612                                cy_as_storage_func_callback);
 613
 614                        if (ret != CY_AS_ERROR_SUCCESS)
 615                                goto destroy;
 616
 617                        /* The request and response are freed
 618                         * as part of the MiscFuncCallback */
 619                        return ret;
 620                }
 621
 622destroy:
 623                cy_as_ll_destroy_request(dev_p, req_p);
 624                cy_as_ll_destroy_response(dev_p, reply_p);
 625        } else if (dev_p->storage_count > 1) {
 626                dev_p->storage_count--;
 627                if (cb)
 628                        cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0);
 629        }
 630
 631        cy_as_device_clear_s_s_s_pending(dev_p);
 632
 633        return ret;
 634}
 635
 636cy_as_return_status_t
 637cy_as_storage_register_callback(cy_as_device_handle handle,
 638        cy_as_storage_event_callback callback)
 639{
 640        cy_as_device *dev_p = (cy_as_device *)handle;
 641        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 642                return CY_AS_ERROR_INVALID_HANDLE;
 643
 644        if (!cy_as_device_is_configured(dev_p))
 645                return CY_AS_ERROR_NOT_CONFIGURED;
 646
 647        if (!cy_as_device_is_firmware_loaded(dev_p))
 648                return CY_AS_ERROR_NO_FIRMWARE;
 649
 650        if (dev_p->storage_count == 0)
 651                return CY_AS_ERROR_NOT_RUNNING;
 652
 653        dev_p->storage_event_cb = NULL;
 654        dev_p->storage_event_cb_ms = callback;
 655
 656        return CY_AS_ERROR_SUCCESS;
 657}
 658
 659
 660
 661static cy_as_return_status_t
 662my_handle_response_storage_claim(cy_as_device *dev_p,
 663                        cy_as_ll_request_response *req_p,
 664                        cy_as_ll_request_response *reply_p)
 665{
 666        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 667
 668        if (cy_as_ll_request_response__get_code(reply_p) ==
 669                CY_RESP_NO_SUCH_ADDRESS) {
 670                ret = cy_as_map_bad_addr(
 671                        cy_as_ll_request_response__get_word(reply_p, 3));
 672                goto destroy;
 673        }
 674
 675        if (cy_as_ll_request_response__get_code(reply_p) !=
 676                CY_RESP_MEDIA_CLAIMED_RELEASED) {
 677                ret = CY_AS_ERROR_INVALID_RESPONSE;
 678                goto destroy;
 679        }
 680
 681        /* The response must be about the address I am
 682         * trying to claim or the firmware is broken */
 683        if ((cy_as_storage_get_bus_from_address(
 684                        cy_as_ll_request_response__get_word(req_p, 0)) !=
 685                cy_as_storage_get_bus_from_address(
 686                        cy_as_ll_request_response__get_word(reply_p, 0))) ||
 687                (cy_as_storage_get_device_from_address(
 688                        cy_as_ll_request_response__get_word(req_p, 0)) !=
 689                cy_as_storage_get_device_from_address(
 690                        cy_as_ll_request_response__get_word(reply_p, 0)))) {
 691                ret = CY_AS_ERROR_INVALID_RESPONSE;
 692                goto destroy;
 693        }
 694
 695        if (cy_as_ll_request_response__get_word(reply_p, 1) != 1)
 696                ret = CY_AS_ERROR_NOT_ACQUIRED;
 697
 698destroy:
 699        cy_as_ll_destroy_request(dev_p, req_p);
 700        cy_as_ll_destroy_response(dev_p, reply_p);
 701
 702        return ret;
 703}
 704
 705static cy_as_return_status_t
 706my_storage_claim(cy_as_device *dev_p,
 707                                void *data,
 708                                cy_as_bus_number_t bus,
 709                                uint32_t device,
 710                                uint16_t req_flags,
 711                                cy_as_function_callback cb,
 712                                uint32_t client)
 713{
 714        cy_as_ll_request_response *req_p , *reply_p;
 715        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 716
 717        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 718                return CY_AS_ERROR_INVALID_HANDLE;
 719
 720        ret = is_storage_active(dev_p);
 721        if (ret != CY_AS_ERROR_SUCCESS)
 722                return ret;
 723
 724        if (dev_p->mtp_count > 0)
 725                return CY_AS_ERROR_NOT_VALID_IN_MTP;
 726
 727        /* Create the request to send to the West Bridge device */
 728        req_p = cy_as_ll_create_request(dev_p,
 729                CY_RQT_CLAIM_STORAGE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
 730        if (req_p == 0)
 731                return CY_AS_ERROR_OUT_OF_MEMORY;
 732
 733        cy_as_ll_request_response__set_word(req_p,
 734                0, create_address(bus, device, 0));
 735
 736        /* Reserve space for the reply, the reply data will
 737         * not exceed one word */
 738        reply_p = cy_as_ll_create_response(dev_p, 4);
 739        if (reply_p == 0) {
 740                cy_as_ll_destroy_request(dev_p, req_p);
 741                return CY_AS_ERROR_OUT_OF_MEMORY;
 742        }
 743
 744        if (cb == 0) {
 745                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
 746                if (ret != CY_AS_ERROR_SUCCESS)
 747                        goto destroy;
 748
 749                return my_handle_response_storage_claim(dev_p, req_p, reply_p);
 750        } else {
 751                ret = cy_as_misc_send_request(dev_p, cb, client,
 752                        CY_FUNCT_CB_STOR_CLAIM, data, dev_p->func_cbs_stor,
 753                        req_flags, req_p, reply_p,
 754                        cy_as_storage_func_callback);
 755
 756                if (ret != CY_AS_ERROR_SUCCESS)
 757                        goto destroy;
 758
 759                /* The request and response are freed as part of
 760                 * the MiscFuncCallback */
 761                return ret;
 762        }
 763
 764destroy:
 765        cy_as_ll_destroy_request(dev_p, req_p);
 766        cy_as_ll_destroy_response(dev_p, reply_p);
 767
 768        return ret;
 769}
 770
 771cy_as_return_status_t
 772cy_as_storage_claim(cy_as_device_handle handle,
 773                                   cy_as_bus_number_t bus,
 774                                   uint32_t device,
 775                                   cy_as_function_callback cb,
 776                                   uint32_t client)
 777{
 778        cy_as_device *dev_p = (cy_as_device *)handle;
 779
 780        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
 781                return CY_AS_ERROR_NO_SUCH_BUS;
 782
 783        return my_storage_claim(dev_p, NULL, bus, device,
 784                CY_AS_REQUEST_RESPONSE_MS, cb, client);
 785}
 786
 787static cy_as_return_status_t
 788my_handle_response_storage_release(cy_as_device *dev_p,
 789                                cy_as_ll_request_response *req_p,
 790                                cy_as_ll_request_response *reply_p)
 791{
 792        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 793
 794        if (cy_as_ll_request_response__get_code(reply_p) ==
 795                CY_RESP_NO_SUCH_ADDRESS) {
 796                ret = cy_as_map_bad_addr(
 797                        cy_as_ll_request_response__get_word(reply_p, 3));
 798                goto destroy;
 799        }
 800
 801        if (cy_as_ll_request_response__get_code(reply_p) !=
 802                CY_RESP_MEDIA_CLAIMED_RELEASED) {
 803                ret = CY_AS_ERROR_INVALID_RESPONSE;
 804                goto destroy;
 805        }
 806
 807        /* The response must be about the address I am
 808         * trying to release or the firmware is broken */
 809        if ((cy_as_storage_get_bus_from_address(
 810                        cy_as_ll_request_response__get_word(req_p, 0)) !=
 811                cy_as_storage_get_bus_from_address(
 812                        cy_as_ll_request_response__get_word(reply_p, 0))) ||
 813                (cy_as_storage_get_device_from_address(
 814                        cy_as_ll_request_response__get_word(req_p, 0)) !=
 815                cy_as_storage_get_device_from_address(
 816                        cy_as_ll_request_response__get_word(reply_p, 0)))) {
 817                ret = CY_AS_ERROR_INVALID_RESPONSE;
 818                goto destroy;
 819        }
 820
 821
 822        if (cy_as_ll_request_response__get_word(reply_p, 1) != 0)
 823                ret = CY_AS_ERROR_NOT_RELEASED;
 824
 825destroy:
 826        cy_as_ll_destroy_request(dev_p, req_p);
 827        cy_as_ll_destroy_response(dev_p, reply_p);
 828
 829        return ret;
 830}
 831
 832static cy_as_return_status_t
 833my_storage_release(cy_as_device *dev_p,
 834                                        void *data,
 835                                        cy_as_bus_number_t bus,
 836                                        uint32_t device,
 837                                        uint16_t req_flags,
 838                                        cy_as_function_callback cb,
 839                                        uint32_t client)
 840{
 841        cy_as_ll_request_response *req_p , *reply_p;
 842        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 843
 844        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 845                return CY_AS_ERROR_INVALID_HANDLE;
 846
 847        ret = is_storage_active(dev_p);
 848        if (ret != CY_AS_ERROR_SUCCESS)
 849                return ret;
 850
 851        if (dev_p->mtp_count > 0)
 852                return CY_AS_ERROR_NOT_VALID_IN_MTP;
 853
 854        /* Create the request to send to the West Bridge device */
 855        req_p = cy_as_ll_create_request(dev_p, CY_RQT_RELEASE_STORAGE,
 856                CY_RQT_STORAGE_RQT_CONTEXT, 1);
 857        if (req_p == 0)
 858                return CY_AS_ERROR_OUT_OF_MEMORY;
 859
 860        cy_as_ll_request_response__set_word(
 861                req_p, 0, create_address(bus, device, 0));
 862
 863        /* Reserve space for the reply, the reply
 864         * data will not exceed one word */
 865        reply_p = cy_as_ll_create_response(dev_p, 4);
 866        if (reply_p == 0) {
 867                cy_as_ll_destroy_request(dev_p, req_p);
 868                return CY_AS_ERROR_OUT_OF_MEMORY;
 869        }
 870
 871        if (cb == 0) {
 872                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
 873                if (ret != CY_AS_ERROR_SUCCESS)
 874                        goto destroy;
 875
 876                return my_handle_response_storage_release(
 877                        dev_p, req_p, reply_p);
 878        } else {
 879                ret = cy_as_misc_send_request(dev_p, cb, client,
 880                        CY_FUNCT_CB_STOR_RELEASE, data, dev_p->func_cbs_stor,
 881                        req_flags, req_p, reply_p,
 882                        cy_as_storage_func_callback);
 883
 884                if (ret != CY_AS_ERROR_SUCCESS)
 885                        goto destroy;
 886
 887                /* The request and response are freed as
 888                 * part of the MiscFuncCallback */
 889                return ret;
 890        }
 891
 892destroy:
 893        cy_as_ll_destroy_request(dev_p, req_p);
 894        cy_as_ll_destroy_response(dev_p, reply_p);
 895
 896        return ret;
 897}
 898
 899cy_as_return_status_t
 900cy_as_storage_release(cy_as_device_handle handle,
 901                                   cy_as_bus_number_t bus,
 902                                   uint32_t device,
 903                                   cy_as_function_callback cb,
 904                                   uint32_t client)
 905{
 906        cy_as_device *dev_p = (cy_as_device *)handle;
 907
 908        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
 909                return CY_AS_ERROR_NO_SUCH_BUS;
 910
 911        return my_storage_release(dev_p, NULL, bus, device,
 912                CY_AS_REQUEST_RESPONSE_MS, cb, client);
 913}
 914
 915static cy_as_return_status_t
 916my_handle_response_storage_query_bus(cy_as_device *dev_p,
 917                                cy_as_ll_request_response *req_p,
 918                                cy_as_ll_request_response *reply_p,
 919                                uint32_t *count)
 920{
 921        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
 922        uint8_t code = cy_as_ll_request_response__get_code(reply_p);
 923        uint16_t v;
 924
 925        if (code == CY_RESP_NO_SUCH_ADDRESS) {
 926                ret = CY_AS_ERROR_NO_SUCH_BUS;
 927                goto destroy;
 928        }
 929
 930        if (code != CY_RESP_BUS_DESCRIPTOR) {
 931                ret = CY_AS_ERROR_INVALID_RESPONSE;
 932                goto destroy;
 933        }
 934
 935        /*
 936         * verify that the response corresponds to the bus that was queried.
 937         */
 938        if (cy_as_storage_get_bus_from_address(
 939                cy_as_ll_request_response__get_word(req_p, 0)) !=
 940                cy_as_storage_get_bus_from_address(
 941                cy_as_ll_request_response__get_word(reply_p, 0))) {
 942                ret = CY_AS_ERROR_INVALID_RESPONSE;
 943                goto destroy;
 944        }
 945
 946        v = cy_as_ll_request_response__get_word(reply_p, 1);
 947        if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
 948                /*
 949                 * this request is only for the count of devices
 950                 * on the bus. there is no need to check the media type.
 951                 */
 952                if (v)
 953                        *count = 1;
 954                else
 955                        *count = 0;
 956        } else {
 957                /*
 958                 * this request is for the count of devices of a
 959                 * particular type. we need to check whether the media
 960                 * type found matches the queried type.
 961                 */
 962                cy_as_media_type queried = (cy_as_media_type)
 963                        cy_as_ll_request_response__get_word(req_p, 1);
 964                cy_as_media_type found =
 965                        cy_as_storage_get_media_from_address(v);
 966
 967                if (queried == found)
 968                        *count = 1;
 969                else
 970                        *count = 0;
 971        }
 972
 973destroy:
 974        cy_as_ll_destroy_request(dev_p, req_p);
 975        cy_as_ll_destroy_response(dev_p, reply_p);
 976
 977        return ret;
 978}
 979
 980cy_as_return_status_t
 981my_storage_query_bus(cy_as_device *dev_p,
 982                                                cy_as_bus_number_t bus,
 983                                                cy_as_media_type   type,
 984                                                uint16_t req_flags,
 985                                                uint32_t *count,
 986                                                cy_as_function_callback cb,
 987                                                uint32_t client)
 988{
 989        cy_as_return_status_t ret;
 990        cy_as_ll_request_response *req_p, *reply_p;
 991        cy_as_funct_c_b_type cb_type = CY_FUNCT_CB_STOR_QUERYBUS;
 992
 993        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
 994                return CY_AS_ERROR_INVALID_HANDLE;
 995
 996        ret = is_storage_active(dev_p);
 997        if (ret != CY_AS_ERROR_SUCCESS)
 998                return ret;
 999
1000        /* Create the request to send to the Antioch device */
1001        req_p = cy_as_ll_create_request(dev_p,
1002                CY_RQT_QUERY_BUS, CY_RQT_STORAGE_RQT_CONTEXT, 2);
1003        if (req_p == 0)
1004                return CY_AS_ERROR_OUT_OF_MEMORY;
1005
1006        cy_as_ll_request_response__set_word(req_p,
1007                0, create_address(bus, 0, 0));
1008        cy_as_ll_request_response__set_word(req_p, 1, (uint16_t)type);
1009
1010        /* Reserve space for the reply, the reply data
1011         * will not exceed two words. */
1012        reply_p = cy_as_ll_create_response(dev_p, 2);
1013        if (reply_p == 0) {
1014                cy_as_ll_destroy_request(dev_p, req_p);
1015                return CY_AS_ERROR_OUT_OF_MEMORY;
1016        }
1017
1018        if (cb == 0) {
1019                ret = cy_as_ll_send_request_wait_reply(dev_p,
1020                        req_p, reply_p);
1021                if (ret != CY_AS_ERROR_SUCCESS)
1022                        goto destroy;
1023
1024                req_p->flags |= req_flags;
1025                return my_handle_response_storage_query_bus(dev_p,
1026                        req_p, reply_p, count);
1027        } else {
1028                if (req_flags == CY_AS_REQUEST_RESPONSE_EX)
1029                        cb_type = CY_FUNCT_CB_STOR_QUERYMEDIA;
1030
1031                ret = cy_as_misc_send_request(dev_p, cb, client, cb_type,
1032                        count, dev_p->func_cbs_stor, req_flags,
1033                        req_p, reply_p, cy_as_storage_func_callback);
1034
1035                if (ret != CY_AS_ERROR_SUCCESS)
1036                        goto destroy;
1037
1038                /* The request and response are freed as part of
1039                 * the MiscFuncCallback */
1040                return ret;
1041        }
1042
1043destroy:
1044        cy_as_ll_destroy_request(dev_p, req_p);
1045        cy_as_ll_destroy_response(dev_p, reply_p);
1046
1047        return ret;
1048}
1049
1050cy_as_return_status_t
1051cy_as_storage_query_bus(cy_as_device_handle handle,
1052                                                cy_as_bus_number_t bus,
1053                                                uint32_t *count,
1054                                                cy_as_function_callback cb,
1055                                                uint32_t client)
1056{
1057        cy_as_device *dev_p = (cy_as_device *)handle;
1058
1059        return my_storage_query_bus(dev_p, bus, cy_as_media_max_media_value,
1060                CY_AS_REQUEST_RESPONSE_MS, count, cb, client);
1061}
1062
1063cy_as_return_status_t
1064cy_as_storage_query_media(cy_as_device_handle handle,
1065                                                cy_as_media_type type,
1066                                                uint32_t *count,
1067                                                cy_as_function_callback cb,
1068                                                uint32_t client)
1069{
1070        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1071        cy_as_bus_number_t bus;
1072
1073        cy_as_device *dev_p = (cy_as_device *)handle;
1074
1075        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1076                return CY_AS_ERROR_INVALID_HANDLE;
1077
1078        ret = is_storage_active(dev_p);
1079        if (ret != CY_AS_ERROR_SUCCESS)
1080                return ret;
1081
1082        ret = cy_an_map_bus_from_media_type(dev_p, type, &bus);
1083        if (ret != CY_AS_ERROR_SUCCESS)
1084                return ret;
1085
1086        return my_storage_query_bus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
1087                        count, cb, client);
1088}
1089
1090static cy_as_return_status_t
1091my_handle_response_storage_query_device(cy_as_device *dev_p,
1092                                cy_as_ll_request_response *req_p,
1093                                cy_as_ll_request_response *reply_p,
1094                                void *data_p)
1095{
1096        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1097        uint16_t v;
1098        cy_as_bus_number_t bus;
1099        cy_as_media_type type;
1100        uint32_t device;
1101        cy_bool removable;
1102        cy_bool writeable;
1103        cy_bool locked;
1104        uint16_t block_size;
1105        uint32_t number_units;
1106        uint32_t number_eus;
1107
1108        if (cy_as_ll_request_response__get_code(reply_p)
1109                == CY_RESP_NO_SUCH_ADDRESS) {
1110                ret = cy_as_map_bad_addr(
1111                        cy_as_ll_request_response__get_word(reply_p, 3));
1112                goto destroy;
1113        }
1114
1115        if (cy_as_ll_request_response__get_code(reply_p) !=
1116        CY_RESP_DEVICE_DESCRIPTOR) {
1117                ret = CY_AS_ERROR_INVALID_RESPONSE;
1118                goto destroy;
1119        }
1120
1121        /* Unpack the response */
1122        v = cy_as_ll_request_response__get_word(reply_p, 0);
1123        type = cy_as_storage_get_media_from_address(v);
1124        bus  = cy_as_storage_get_bus_from_address(v);
1125        device = cy_as_storage_get_device_from_address(v);
1126
1127        block_size = cy_as_ll_request_response__get_word(reply_p, 1);
1128
1129        v = cy_as_ll_request_response__get_word(reply_p, 2);
1130        removable = (v & 0x8000) ? cy_true : cy_false;
1131        writeable = (v & 0x0100) ? cy_true : cy_false;
1132        locked = (v & 0x0200) ? cy_true : cy_false;
1133        number_units = (v & 0xff);
1134
1135        number_eus  = (cy_as_ll_request_response__get_word(reply_p, 3) << 16)
1136                | cy_as_ll_request_response__get_word(reply_p, 4);
1137
1138        /* Store the results based on the version of originating function */
1139        if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
1140                cy_as_storage_query_device_data  *store_p =
1141                        (cy_as_storage_query_device_data *)data_p;
1142
1143                /* Make sure the response is about the address we asked
1144                 * about - if not, firmware error */
1145                if ((bus != store_p->bus) || (device != store_p->device)) {
1146                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1147                        goto destroy;
1148                }
1149
1150                store_p->desc_p.type = type;
1151                store_p->desc_p.removable = removable;
1152                store_p->desc_p.writeable = writeable;
1153                store_p->desc_p.block_size = block_size;
1154                store_p->desc_p.number_units = number_units;
1155                store_p->desc_p.locked = locked;
1156                store_p->desc_p.erase_unit_size = number_eus;
1157                dev_p->storage_device_info[bus][device] = store_p->desc_p;
1158        } else {
1159                cy_as_storage_query_device_data_dep     *store_p =
1160                        (cy_as_storage_query_device_data_dep *)data_p;
1161
1162                /* Make sure the response is about the address we asked
1163                 * about - if not, firmware error */
1164                if ((type != store_p->type) || (device != store_p->device)) {
1165                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1166                        goto destroy;
1167                }
1168
1169                store_p->desc_p.type = type;
1170                store_p->desc_p.removable = removable;
1171                store_p->desc_p.writeable = writeable;
1172                store_p->desc_p.block_size = block_size;
1173                store_p->desc_p.number_units = number_units;
1174                store_p->desc_p.locked = locked;
1175                store_p->desc_p.erase_unit_size = number_eus;
1176                dev_p->storage_device_info[bus][device] = store_p->desc_p;
1177        }
1178
1179destroy:
1180        cy_as_ll_destroy_request(dev_p, req_p);
1181        cy_as_ll_destroy_response(dev_p, reply_p);
1182
1183        return ret;
1184}
1185
1186static cy_as_return_status_t
1187my_storage_query_device(cy_as_device *dev_p,
1188                                                void *data_p,
1189                                                uint16_t req_flags,
1190                                                cy_as_bus_number_t bus,
1191                                                uint32_t device,
1192                                                cy_as_function_callback cb,
1193                                                uint32_t client)
1194{
1195        cy_as_ll_request_response *req_p , *reply_p;
1196        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1197
1198        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1199                return CY_AS_ERROR_INVALID_HANDLE;
1200
1201        ret = is_storage_active(dev_p);
1202        if (ret != CY_AS_ERROR_SUCCESS)
1203                return ret;
1204
1205        /* Create the request to send to the Antioch device */
1206        req_p = cy_as_ll_create_request(dev_p,
1207                CY_RQT_QUERY_DEVICE, CY_RQT_STORAGE_RQT_CONTEXT, 1);
1208        if (req_p == 0)
1209                return CY_AS_ERROR_OUT_OF_MEMORY;
1210
1211        cy_as_ll_request_response__set_word(req_p, 0,
1212                create_address(bus, device, 0));
1213
1214        /* Reserve space for the reply, the reply data
1215         * will not exceed five words. */
1216        reply_p = cy_as_ll_create_response(dev_p, 5);
1217        if (reply_p == 0) {
1218                cy_as_ll_destroy_request(dev_p, req_p);
1219                return CY_AS_ERROR_OUT_OF_MEMORY;
1220        }
1221
1222        if (cb == 0) {
1223                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1224                if (ret != CY_AS_ERROR_SUCCESS)
1225                        goto destroy;
1226
1227                req_p->flags |= req_flags;
1228                return my_handle_response_storage_query_device(dev_p,
1229                        req_p, reply_p, data_p);
1230        } else {
1231
1232                ret = cy_as_misc_send_request(dev_p, cb, client,
1233                        CY_FUNCT_CB_STOR_QUERYDEVICE, data_p,
1234                        dev_p->func_cbs_stor, req_flags, req_p,
1235                        reply_p, cy_as_storage_func_callback);
1236
1237                if (ret != CY_AS_ERROR_SUCCESS)
1238                        goto destroy;
1239
1240                /* The request and response are freed as part of the
1241                 * MiscFuncCallback */
1242                return ret;
1243        }
1244
1245destroy:
1246        cy_as_ll_destroy_request(dev_p, req_p);
1247        cy_as_ll_destroy_response(dev_p, reply_p);
1248
1249        return ret;
1250}
1251
1252cy_as_return_status_t
1253cy_as_storage_query_device(cy_as_device_handle handle,
1254                        cy_as_storage_query_device_data *data_p,
1255                        cy_as_function_callback cb,
1256                        uint32_t client)
1257{
1258        cy_as_device *dev_p = (cy_as_device *)handle;
1259        return my_storage_query_device(dev_p, data_p,
1260                CY_AS_REQUEST_RESPONSE_MS, data_p->bus,
1261                        data_p->device, cb, client);
1262}
1263
1264static cy_as_return_status_t
1265my_handle_response_storage_query_unit(cy_as_device *dev_p,
1266                        cy_as_ll_request_response *req_p,
1267                        cy_as_ll_request_response *reply_p,
1268                        void *data_p)
1269{
1270        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1271        cy_as_bus_number_t bus;
1272        uint32_t device;
1273        uint32_t unit;
1274        cy_as_media_type type;
1275        uint16_t block_size;
1276        uint32_t start_block;
1277        uint32_t unit_size;
1278        uint16_t v;
1279
1280        if (cy_as_ll_request_response__get_code(reply_p) ==
1281        CY_RESP_NO_SUCH_ADDRESS) {
1282                ret = cy_as_map_bad_addr(
1283                        cy_as_ll_request_response__get_word(reply_p, 3));
1284                goto destroy;
1285        }
1286
1287        if (cy_as_ll_request_response__get_code(reply_p) !=
1288        CY_RESP_UNIT_DESCRIPTOR) {
1289                ret = CY_AS_ERROR_INVALID_RESPONSE;
1290                goto destroy;
1291        }
1292
1293        /* Unpack the response */
1294        v         = cy_as_ll_request_response__get_word(reply_p, 0);
1295        bus     = cy_as_storage_get_bus_from_address(v);
1296        device = cy_as_storage_get_device_from_address(v);
1297        unit   = get_unit_from_address(v);
1298
1299        type   = cy_as_storage_get_media_from_address(
1300                cy_as_ll_request_response__get_word(reply_p, 1));
1301
1302        block_size = cy_as_ll_request_response__get_word(reply_p, 2);
1303        start_block = cy_as_ll_request_response__get_word(reply_p, 3)
1304                | (cy_as_ll_request_response__get_word(reply_p, 4) << 16);
1305        unit_size = cy_as_ll_request_response__get_word(reply_p, 5)
1306                | (cy_as_ll_request_response__get_word(reply_p, 6) << 16);
1307
1308        /* Store the results based on the version of
1309         * originating function */
1310        if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
1311                cy_as_storage_query_unit_data  *store_p =
1312                        (cy_as_storage_query_unit_data *)data_p;
1313
1314                /* Make sure the response is about the address we
1315                 * asked about - if not, firmware error */
1316                if (bus != store_p->bus || device != store_p->device ||
1317                unit != store_p->unit) {
1318                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1319                        goto destroy;
1320                }
1321
1322                store_p->desc_p.type = type;
1323                store_p->desc_p.block_size = block_size;
1324                store_p->desc_p.start_block = start_block;
1325                store_p->desc_p.unit_size = unit_size;
1326        } else {
1327                cy_as_storage_query_unit_data_dep *store_p =
1328                        (cy_as_storage_query_unit_data_dep *)data_p;
1329
1330                /* Make sure the response is about the media type we asked
1331                 * about - if not, firmware error */
1332                if ((type != store_p->type) || (device != store_p->device) ||
1333                (unit != store_p->unit)) {
1334                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1335                        goto destroy;
1336                }
1337
1338                store_p->desc_p.type = type;
1339                store_p->desc_p.block_size = block_size;
1340                store_p->desc_p.start_block = start_block;
1341                store_p->desc_p.unit_size = unit_size;
1342        }
1343
1344        dev_p->storage_device_info[bus][device].type = type;
1345        dev_p->storage_device_info[bus][device].block_size = block_size;
1346
1347destroy:
1348        cy_as_ll_destroy_request(dev_p, req_p);
1349        cy_as_ll_destroy_response(dev_p, reply_p);
1350
1351        return ret;
1352}
1353
1354static cy_as_return_status_t
1355my_storage_query_unit(cy_as_device *dev_p,
1356                                        void *data_p,
1357                                        uint16_t req_flags,
1358                                        cy_as_bus_number_t bus,
1359                                        uint32_t device,
1360                                        uint32_t unit,
1361                                        cy_as_function_callback cb,
1362                                        uint32_t client)
1363{
1364        cy_as_ll_request_response *req_p , *reply_p;
1365        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1366
1367        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1368                return CY_AS_ERROR_INVALID_HANDLE;
1369
1370        ret = is_storage_active(dev_p);
1371        if (ret != CY_AS_ERROR_SUCCESS)
1372                return ret;
1373
1374        /* Create the request to send to the West Bridge device */
1375        req_p = cy_as_ll_create_request(dev_p,
1376        CY_RQT_QUERY_UNIT, CY_RQT_STORAGE_RQT_CONTEXT, 1);
1377        if (req_p == 0)
1378                return CY_AS_ERROR_OUT_OF_MEMORY;
1379
1380        if (device > 255)
1381                return CY_AS_ERROR_NO_SUCH_DEVICE;
1382
1383        if (unit > 255)
1384                return CY_AS_ERROR_NO_SUCH_UNIT;
1385
1386        cy_as_ll_request_response__set_word(req_p, 0,
1387                create_address(bus, device, (uint8_t)unit));
1388
1389        /* Reserve space for the reply, the reply data
1390         * will be of seven words. */
1391        reply_p = cy_as_ll_create_response(dev_p, 7);
1392        if (reply_p == 0) {
1393                cy_as_ll_destroy_request(dev_p, req_p);
1394                return CY_AS_ERROR_OUT_OF_MEMORY;
1395        }
1396
1397        if (cb == 0) {
1398                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1399                if (ret != CY_AS_ERROR_SUCCESS)
1400                        goto destroy;
1401
1402                req_p->flags |= req_flags;
1403                return my_handle_response_storage_query_unit(dev_p,
1404                        req_p, reply_p, data_p);
1405        } else {
1406
1407                ret = cy_as_misc_send_request(dev_p, cb, client,
1408                        CY_FUNCT_CB_STOR_QUERYUNIT, data_p,
1409                        dev_p->func_cbs_stor, req_flags, req_p, reply_p,
1410                        cy_as_storage_func_callback);
1411
1412                if (ret != CY_AS_ERROR_SUCCESS)
1413                        goto destroy;
1414
1415                /* The request and response are freed
1416                 * as part of the MiscFuncCallback */
1417                return ret;
1418        }
1419
1420destroy:
1421        cy_as_ll_destroy_request(dev_p, req_p);
1422        cy_as_ll_destroy_response(dev_p, reply_p);
1423
1424        return ret;
1425}
1426
1427cy_as_return_status_t
1428cy_as_storage_query_unit(cy_as_device_handle handle,
1429                                cy_as_storage_query_unit_data *data_p,
1430                                cy_as_function_callback cb,
1431                                uint32_t client)
1432{
1433        cy_as_device *dev_p = (cy_as_device *)handle;
1434        return my_storage_query_unit(dev_p, data_p, CY_AS_REQUEST_RESPONSE_MS,
1435                data_p->bus, data_p->device, data_p->unit, cb, client);
1436}
1437
1438
1439static cy_as_return_status_t
1440cy_as_get_block_size(cy_as_device *dev_p,
1441                                        cy_as_bus_number_t bus,
1442                                        uint32_t device,
1443                                        cy_as_function_callback cb)
1444{
1445        cy_as_ll_request_response *req_p , *reply_p;
1446        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1447
1448        /* Create the request to send to the West Bridge device */
1449        req_p = cy_as_ll_create_request(dev_p, CY_RQT_QUERY_DEVICE,
1450                CY_RQT_STORAGE_RQT_CONTEXT, 1);
1451        if (req_p == 0)
1452                return CY_AS_ERROR_OUT_OF_MEMORY;
1453
1454        cy_as_ll_request_response__set_word(req_p, 0,
1455                create_address(bus, device, 0));
1456
1457        reply_p = cy_as_ll_create_response(dev_p, 4);
1458        if (reply_p == 0) {
1459                cy_as_ll_destroy_request(dev_p, req_p);
1460                return CY_AS_ERROR_OUT_OF_MEMORY;
1461        }
1462
1463        if (cb == 0) {
1464                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1465                if (ret != CY_AS_ERROR_SUCCESS)
1466                        goto destroy;
1467
1468                if (cy_as_ll_request_response__get_code(reply_p)
1469                == CY_RESP_NO_SUCH_ADDRESS) {
1470                        ret = CY_AS_ERROR_NO_SUCH_BUS;
1471                        goto destroy;
1472                }
1473
1474                if (cy_as_ll_request_response__get_code(reply_p) !=
1475                CY_RESP_DEVICE_DESCRIPTOR) {
1476                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1477                        goto destroy;
1478                }
1479
1480                /* Make sure the response is about the media type we asked
1481                 * about - if not, firmware error */
1482                if ((cy_as_storage_get_bus_from_address
1483                        (cy_as_ll_request_response__get_word(reply_p, 0))
1484                        != bus) || (cy_as_storage_get_device_from_address
1485                        (cy_as_ll_request_response__get_word(reply_p, 0))
1486                        != device)) {
1487                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1488                        goto destroy;
1489                }
1490
1491
1492                dev_p->storage_device_info[bus][device].block_size =
1493                        cy_as_ll_request_response__get_word(reply_p, 1);
1494        } else
1495                ret = CY_AS_ERROR_INVALID_REQUEST;
1496
1497destroy:
1498        cy_as_ll_destroy_request(dev_p, req_p);
1499        cy_as_ll_destroy_response(dev_p, reply_p);
1500
1501        return ret;
1502}
1503
1504cy_as_return_status_t
1505my_storage_device_control(
1506                cy_as_device              *dev_p,
1507                cy_as_bus_number_t        bus,
1508                uint32_t                         device,
1509                cy_bool                    card_detect_en,
1510                cy_bool                    write_prot_en,
1511                                cy_as_storage_card_detect config_detect,
1512                cy_as_function_callback cb,
1513                uint32_t                         client)
1514{
1515        cy_as_ll_request_response *req_p , *reply_p;
1516        cy_as_return_status_t ret;
1517        cy_bool use_gpio = cy_false;
1518
1519        (void)device;
1520
1521        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1522                return CY_AS_ERROR_INVALID_HANDLE;
1523
1524        if (!cy_as_device_is_configured(dev_p))
1525                return CY_AS_ERROR_NOT_CONFIGURED;
1526
1527        if (!cy_as_device_is_firmware_loaded(dev_p))
1528                return CY_AS_ERROR_NO_FIRMWARE;
1529
1530        if (cy_as_device_is_in_suspend_mode(dev_p))
1531                return CY_AS_ERROR_IN_SUSPEND;
1532
1533        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1534                return CY_AS_ERROR_NO_SUCH_BUS;
1535
1536        if (device >= CY_AS_MAX_STORAGE_DEVICES)
1537                return CY_AS_ERROR_NO_SUCH_DEVICE;
1538
1539        /* If SD is not supported on the specified bus,
1540         * then return ERROR */
1541        if ((dev_p->media_supported[bus] == 0) ||
1542                (dev_p->media_supported[bus] & (1<<cy_as_media_nand)))
1543                return CY_AS_ERROR_NOT_SUPPORTED;
1544
1545        if (config_detect == cy_as_storage_detect_GPIO)
1546                use_gpio = cy_true;
1547        else if (config_detect == cy_as_storage_detect_SDAT_3)
1548                use_gpio = cy_false;
1549        else
1550                return CY_AS_ERROR_INVALID_PARAMETER;
1551
1552        /* Create the request to send to the West Bridge device */
1553        req_p = cy_as_ll_create_request(dev_p,
1554                CY_RQT_SD_INTERFACE_CONTROL, CY_RQT_STORAGE_RQT_CONTEXT, 2);
1555        if (req_p == 0)
1556                return CY_AS_ERROR_OUT_OF_MEMORY;
1557
1558        cy_as_ll_request_response__set_word(req_p,
1559                0, create_address(bus, device, 0));
1560        cy_as_ll_request_response__set_word(req_p,
1561                1, (((uint16_t)card_detect_en << 8) |
1562                ((uint16_t)use_gpio << 1) | (uint16_t)write_prot_en));
1563
1564        reply_p = cy_as_ll_create_response(dev_p, 1);
1565        if (reply_p == 0) {
1566                cy_as_ll_destroy_request(dev_p, req_p);
1567                return CY_AS_ERROR_OUT_OF_MEMORY;
1568        }
1569
1570        if (cb == 0) {
1571                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1572                if (ret != CY_AS_ERROR_SUCCESS)
1573                        goto destroy;
1574
1575                if (cy_as_ll_request_response__get_code(reply_p) !=
1576                CY_RESP_SUCCESS_FAILURE) {
1577                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1578                        goto destroy;
1579                }
1580
1581                ret = cy_as_ll_request_response__get_word(reply_p, 0);
1582        } else {
1583
1584                ret = cy_as_misc_send_request(dev_p, cb, client,
1585                        CY_FUNCT_CB_STOR_DEVICECONTROL,
1586                        0, dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
1587                        req_p, reply_p, cy_as_storage_func_callback);
1588
1589                if (ret != CY_AS_ERROR_SUCCESS)
1590                        goto destroy;
1591
1592                /* The request and response are freed as part of the
1593                 * MiscFuncCallback */
1594                return ret;
1595        }
1596destroy:
1597        cy_as_ll_destroy_request(dev_p, req_p);
1598        cy_as_ll_destroy_response(dev_p, reply_p);
1599
1600        return ret;
1601}
1602
1603cy_as_return_status_t
1604cy_as_storage_device_control(cy_as_device_handle handle,
1605                                        cy_as_bus_number_t bus,
1606                                        uint32_t device,
1607                                        cy_bool card_detect_en,
1608                                        cy_bool write_prot_en,
1609                                        cy_as_storage_card_detect config_detect,
1610                                        cy_as_function_callback cb,
1611                                        uint32_t client)
1612{
1613        cy_as_device *dev_p = (cy_as_device *)handle;
1614
1615        return my_storage_device_control(dev_p, bus, device, card_detect_en,
1616                write_prot_en, config_detect, cb, client);
1617}
1618
1619static void
1620cy_as_async_storage_callback(cy_as_device *dev_p,
1621        cy_as_end_point_number_t ep, void *buf_p, uint32_t size,
1622        cy_as_return_status_t ret)
1623{
1624        cy_as_storage_callback_dep cb;
1625        cy_as_storage_callback cb_ms;
1626
1627        (void)size;
1628        (void)buf_p;
1629        (void)ep;
1630
1631        cy_as_device_clear_storage_async_pending(dev_p);
1632
1633        /*
1634        * if the LL request callback has already been called,
1635        * the user callback has to be called from here.
1636        */
1637        if (!dev_p->storage_wait) {
1638                        cy_as_hal_assert(dev_p->storage_cb != NULL ||
1639                                dev_p->storage_cb_ms != NULL);
1640                        cb = dev_p->storage_cb;
1641                        cb_ms = dev_p->storage_cb_ms;
1642
1643                        dev_p->storage_cb = 0;
1644                        dev_p->storage_cb_ms = 0;
1645
1646                        if (ret == CY_AS_ERROR_SUCCESS)
1647                                ret = dev_p->storage_error;
1648
1649                if (cb_ms) {
1650                        cb_ms((cy_as_device_handle)dev_p,
1651                                dev_p->storage_bus_index,
1652                                dev_p->storage_device_index,
1653                                dev_p->storage_unit,
1654                                dev_p->storage_block_addr,
1655                                dev_p->storage_oper, ret);
1656                } else {
1657                        cb((cy_as_device_handle)dev_p,
1658                                dev_p->storage_device_info
1659                                [dev_p->storage_bus_index]
1660                                [dev_p->storage_device_index].type,
1661                                dev_p->storage_device_index,
1662                                dev_p->storage_unit,
1663                                dev_p->storage_block_addr,
1664                                dev_p->storage_oper, ret);
1665                }
1666        } else
1667                dev_p->storage_error = ret;
1668}
1669
1670static void
1671cy_as_async_storage_reply_callback(
1672                                        cy_as_device *dev_p,
1673                                        uint8_t context,
1674                                        cy_as_ll_request_response *rqt,
1675                                        cy_as_ll_request_response *resp,
1676                                        cy_as_return_status_t ret)
1677{
1678        cy_as_storage_callback_dep cb;
1679        cy_as_storage_callback cb_ms;
1680        uint8_t reqtype;
1681        (void)rqt;
1682        (void)context;
1683
1684        reqtype = cy_as_ll_request_response__get_code(rqt);
1685
1686        if (ret == CY_AS_ERROR_SUCCESS) {
1687                if (cy_as_ll_request_response__get_code(resp) ==
1688                        CY_RESP_ANTIOCH_DEFERRED_ERROR) {
1689                        ret = cy_as_ll_request_response__get_word
1690                                (resp, 0) & 0x00FF;
1691                } else if (cy_as_ll_request_response__get_code(resp) !=
1692                        CY_RESP_SUCCESS_FAILURE) {
1693                        ret = CY_AS_ERROR_INVALID_RESPONSE;
1694                }
1695        }
1696
1697        if (ret != CY_AS_ERROR_SUCCESS) {
1698                if (reqtype == CY_RQT_READ_BLOCK)
1699                        cy_as_dma_cancel(dev_p,
1700                                dev_p->storage_read_endpoint, ret);
1701                else
1702                        cy_as_dma_cancel(dev_p,
1703                                dev_p->storage_write_endpoint, ret);
1704        }
1705
1706        dev_p->storage_wait = cy_false;
1707
1708        /*
1709        * if the DMA callback has already been called, the
1710        * user callback has to be called from here.
1711        */
1712        if (!cy_as_device_is_storage_async_pending(dev_p)) {
1713                cy_as_hal_assert(dev_p->storage_cb != NULL ||
1714                        dev_p->storage_cb_ms != NULL);
1715                cb = dev_p->storage_cb;
1716                cb_ms = dev_p->storage_cb_ms;
1717
1718                dev_p->storage_cb = 0;
1719                dev_p->storage_cb_ms = 0;
1720
1721                if (ret == CY_AS_ERROR_SUCCESS)
1722                        ret = dev_p->storage_error;
1723
1724                if (cb_ms) {
1725                        cb_ms((cy_as_device_handle)dev_p,
1726                                dev_p->storage_bus_index,
1727                                dev_p->storage_device_index,
1728                                dev_p->storage_unit,
1729                                dev_p->storage_block_addr,
1730                                dev_p->storage_oper, ret);
1731                } else {
1732                        cb((cy_as_device_handle)dev_p,
1733                                dev_p->storage_device_info
1734                                [dev_p->storage_bus_index]
1735                                [dev_p->storage_device_index].type,
1736                                dev_p->storage_device_index,
1737                                dev_p->storage_unit,
1738                                dev_p->storage_block_addr,
1739                                dev_p->storage_oper, ret);
1740                }
1741        } else
1742                dev_p->storage_error = ret;
1743}
1744
1745static cy_as_return_status_t
1746cy_as_storage_async_oper(cy_as_device *dev_p, cy_as_end_point_number_t ep,
1747                uint8_t reqtype, uint16_t req_flags, cy_as_bus_number_t bus,
1748                uint32_t device, uint32_t unit, uint32_t block, void *data_p,
1749                uint16_t num_blocks, cy_as_storage_callback_dep callback,
1750                cy_as_storage_callback callback_ms)
1751{
1752        uint32_t mask;
1753        cy_as_ll_request_response *req_p , *reply_p;
1754        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1755
1756        ret = is_storage_active(dev_p);
1757        if (ret != CY_AS_ERROR_SUCCESS)
1758                return ret;
1759
1760        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1761                return CY_AS_ERROR_NO_SUCH_BUS;
1762
1763        if (device >= CY_AS_MAX_STORAGE_DEVICES)
1764                return CY_AS_ERROR_NO_SUCH_DEVICE;
1765
1766        if (unit > 255)
1767                return CY_AS_ERROR_NO_SUCH_UNIT;
1768
1769        /* We are supposed to return sucess if the number of
1770        * blocks is zero
1771        */
1772        if (num_blocks == 0) {
1773                if (callback_ms)
1774                        callback_ms((cy_as_device_handle)dev_p,
1775                                bus, device, unit, block,
1776                                ((reqtype == CY_RQT_WRITE_BLOCK)
1777                                ? cy_as_op_write : cy_as_op_read),
1778                                CY_AS_ERROR_SUCCESS);
1779                else
1780                        callback((cy_as_device_handle)dev_p,
1781                                dev_p->storage_device_info[bus][device].type,
1782                                device, unit, block,
1783                                ((reqtype == CY_RQT_WRITE_BLOCK) ?
1784                                        cy_as_op_write : cy_as_op_read),
1785                                CY_AS_ERROR_SUCCESS);
1786
1787                return CY_AS_ERROR_SUCCESS;
1788        }
1789
1790        if (dev_p->storage_device_info[bus][device].block_size == 0)
1791                        return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
1792
1793        /*
1794        * since async operations can be triggered by interrupt
1795        * code, we must insure that we do not get multiple
1796        * async operations going at one time and protect this
1797        * test and set operation from interrupts. also need to
1798        * check for pending async MTP writes
1799        */
1800        mask = cy_as_hal_disable_interrupts();
1801        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
1802        (dev_p->storage_wait) ||
1803        (cy_as_device_is_usb_async_pending(dev_p, 6))) {
1804                cy_as_hal_enable_interrupts(mask);
1805                return CY_AS_ERROR_ASYNC_PENDING;
1806        }
1807
1808        cy_as_device_set_storage_async_pending(dev_p);
1809        cy_as_device_clear_p2s_dma_start_recvd(dev_p);
1810        cy_as_hal_enable_interrupts(mask);
1811
1812        /*
1813        * storage information about the currently outstanding request
1814        */
1815        dev_p->storage_cb = callback;
1816        dev_p->storage_cb_ms = callback_ms;
1817        dev_p->storage_bus_index = bus;
1818        dev_p->storage_device_index = device;
1819        dev_p->storage_unit = unit;
1820        dev_p->storage_block_addr = block;
1821
1822        /* Initialise the request to send to the West Bridge. */
1823        req_p = dev_p->storage_rw_req_p;
1824        cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 5);
1825
1826        /* Initialise the space for reply from the West Bridge. */
1827        reply_p = dev_p->storage_rw_resp_p;
1828        cy_as_ll_init_response(reply_p, 5);
1829
1830        /* Remember which version of the API originated the request */
1831        req_p->flags |= req_flags;
1832
1833        /* Setup the DMA request and adjust the storage
1834         * operation if we are reading */
1835        if (reqtype == CY_RQT_READ_BLOCK) {
1836                ret = cy_as_dma_queue_request(dev_p, ep, data_p,
1837                        dev_p->storage_device_info[bus][device].block_size
1838                        * num_blocks, cy_false, cy_true,
1839                        cy_as_async_storage_callback);
1840                dev_p->storage_oper = cy_as_op_read;
1841        } else if (reqtype == CY_RQT_WRITE_BLOCK) {
1842                ret = cy_as_dma_queue_request(dev_p, ep, data_p,
1843                        dev_p->storage_device_info[bus][device].block_size *
1844                        num_blocks, cy_false, cy_false,
1845                        cy_as_async_storage_callback);
1846                dev_p->storage_oper = cy_as_op_write;
1847        }
1848
1849        if (ret != CY_AS_ERROR_SUCCESS) {
1850                cy_as_device_clear_storage_async_pending(dev_p);
1851                return ret;
1852        }
1853
1854        cy_as_ll_request_response__set_word(req_p,
1855                0, create_address(bus, (uint8_t)device, (uint8_t)unit));
1856        cy_as_ll_request_response__set_word(req_p,
1857                1, (uint16_t)((block >> 16) & 0xffff));
1858        cy_as_ll_request_response__set_word(req_p,
1859                2, (uint16_t)(block & 0xffff));
1860        cy_as_ll_request_response__set_word(req_p,
1861                3, (uint16_t)((num_blocks >> 8) & 0x00ff));
1862        cy_as_ll_request_response__set_word(req_p,
1863                4, (uint16_t)((num_blocks << 8) & 0xff00));
1864
1865        /* Set the burst mode flag. */
1866        if (dev_p->is_storage_only_mode)
1867                req_p->data[4] |= 0x0001;
1868
1869        /* Send the request and wait for completion
1870         * of storage request */
1871        dev_p->storage_wait = cy_true;
1872        ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
1873                cy_true, cy_as_async_storage_reply_callback);
1874        if (ret != CY_AS_ERROR_SUCCESS) {
1875                cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
1876                cy_as_device_clear_storage_async_pending(dev_p);
1877        }
1878
1879        return ret;
1880}
1881
1882static void
1883cy_as_sync_storage_callback(cy_as_device *dev_p,
1884        cy_as_end_point_number_t ep, void *buf_p,
1885        uint32_t size, cy_as_return_status_t err)
1886{
1887        (void)ep;
1888        (void)buf_p;
1889        (void)size;
1890
1891        dev_p->storage_error = err;
1892}
1893
1894static void
1895cy_as_sync_storage_reply_callback(
1896                                cy_as_device *dev_p,
1897                                uint8_t context,
1898                                cy_as_ll_request_response *rqt,
1899                                cy_as_ll_request_response *resp,
1900                                cy_as_return_status_t ret)
1901{
1902        uint8_t reqtype;
1903        (void)rqt;
1904
1905        reqtype = cy_as_ll_request_response__get_code(rqt);
1906
1907        if (cy_as_ll_request_response__get_code(resp) ==
1908        CY_RESP_ANTIOCH_DEFERRED_ERROR) {
1909                ret = cy_as_ll_request_response__get_word(resp, 0) & 0x00FF;
1910
1911                if (ret != CY_AS_ERROR_SUCCESS) {
1912                        if (reqtype == CY_RQT_READ_BLOCK)
1913                                cy_as_dma_cancel(dev_p,
1914                                        dev_p->storage_read_endpoint, ret);
1915                        else
1916                                cy_as_dma_cancel(dev_p,
1917                                        dev_p->storage_write_endpoint, ret);
1918                }
1919        } else if (cy_as_ll_request_response__get_code(resp) !=
1920        CY_RESP_SUCCESS_FAILURE) {
1921                ret = CY_AS_ERROR_INVALID_RESPONSE;
1922        }
1923
1924        dev_p->storage_wait = cy_false;
1925        dev_p->storage_error = ret;
1926
1927        /* Wake any threads/processes that are waiting on
1928         * the read/write completion. */
1929        cy_as_hal_wake(&dev_p->context[context]->channel);
1930}
1931
1932static cy_as_return_status_t
1933cy_as_storage_sync_oper(cy_as_device *dev_p,
1934        cy_as_end_point_number_t ep, uint8_t reqtype,
1935        cy_as_bus_number_t bus, uint32_t device,
1936        uint32_t unit, uint32_t block, void *data_p,
1937        uint16_t num_blocks)
1938{
1939        cy_as_ll_request_response *req_p , *reply_p;
1940        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1941        cy_as_context *ctxt_p;
1942        uint32_t loopcount = 200;
1943
1944        ret = is_storage_active(dev_p);
1945        if (ret != CY_AS_ERROR_SUCCESS)
1946                return ret;
1947
1948        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1949                return CY_AS_ERROR_NO_SUCH_BUS;
1950
1951        if (device >= CY_AS_MAX_STORAGE_DEVICES)
1952                return CY_AS_ERROR_NO_SUCH_DEVICE;
1953
1954        if (unit > 255)
1955                return CY_AS_ERROR_NO_SUCH_UNIT;
1956
1957        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
1958                (dev_p->storage_wait))
1959                return CY_AS_ERROR_ASYNC_PENDING;
1960
1961        /* Also need to check for pending Async MTP writes */
1962        if (cy_as_device_is_usb_async_pending(dev_p, 6))
1963                return CY_AS_ERROR_ASYNC_PENDING;
1964
1965        /* We are supposed to return sucess if the number of
1966        * blocks is zero
1967        */
1968        if (num_blocks == 0)
1969                return CY_AS_ERROR_SUCCESS;
1970
1971        if (dev_p->storage_device_info[bus][device].block_size == 0) {
1972                /*
1973                * normally, a given device has been queried via
1974                * the query device call before a read request is issued.
1975                * therefore, this normally will not be run.
1976                */
1977                ret = cy_as_get_block_size(dev_p, bus, device, 0);
1978                if (ret != CY_AS_ERROR_SUCCESS)
1979                        return ret;
1980        }
1981
1982        /* Initialise the request to send to the West Bridge. */
1983        req_p = dev_p->storage_rw_req_p;
1984        cy_as_ll_init_request(req_p, reqtype,
1985                CY_RQT_STORAGE_RQT_CONTEXT, 5);
1986
1987        /* Initialise the space for reply from
1988         * the West Bridge. */
1989        reply_p = dev_p->storage_rw_resp_p;
1990        cy_as_ll_init_response(reply_p, 5);
1991        cy_as_device_clear_p2s_dma_start_recvd(dev_p);
1992
1993        /* Setup the DMA request */
1994        if (reqtype == CY_RQT_READ_BLOCK) {
1995                ret = cy_as_dma_queue_request(dev_p, ep, data_p,
1996                        dev_p->storage_device_info[bus][device].block_size *
1997                        num_blocks, cy_false,
1998                        cy_true, cy_as_sync_storage_callback);
1999                dev_p->storage_oper = cy_as_op_read;
2000        } else if (reqtype == CY_RQT_WRITE_BLOCK) {
2001                ret = cy_as_dma_queue_request(dev_p, ep, data_p,
2002                        dev_p->storage_device_info[bus][device].block_size *
2003                        num_blocks, cy_false, cy_false,
2004                        cy_as_sync_storage_callback);
2005                dev_p->storage_oper = cy_as_op_write;
2006        }
2007
2008        if (ret != CY_AS_ERROR_SUCCESS)
2009                return ret;
2010
2011        cy_as_ll_request_response__set_word(req_p, 0,
2012                create_address(bus, (uint8_t)device, (uint8_t)unit));
2013        cy_as_ll_request_response__set_word(req_p, 1,
2014                (uint16_t)((block >> 16) & 0xffff));
2015        cy_as_ll_request_response__set_word(req_p, 2,
2016                (uint16_t)(block & 0xffff));
2017        cy_as_ll_request_response__set_word(req_p, 3,
2018                (uint16_t)((num_blocks >> 8) & 0x00ff));
2019        cy_as_ll_request_response__set_word(req_p, 4,
2020                (uint16_t)((num_blocks << 8) & 0xff00));
2021
2022        /* Set the burst mode flag. */
2023        if (dev_p->is_storage_only_mode)
2024                req_p->data[4] |= 0x0001;
2025
2026        /* Send the request and wait for
2027         * completion of storage request */
2028        dev_p->storage_wait = cy_true;
2029        ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
2030                cy_as_sync_storage_reply_callback);
2031        if (ret != CY_AS_ERROR_SUCCESS) {
2032                cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
2033        } else {
2034                /* Setup the DMA request */
2035                ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
2036                ret = cy_as_dma_drain_queue(dev_p, ep, cy_false);
2037
2038                while (loopcount-- > 0) {
2039                        if (dev_p->storage_wait == cy_false)
2040                                break;
2041                        cy_as_hal_sleep_on(&ctxt_p->channel, 10);
2042                }
2043
2044                if (dev_p->storage_wait == cy_true) {
2045                        dev_p->storage_wait = cy_false;
2046                        cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
2047                        ret = CY_AS_ERROR_TIMEOUT;
2048                }
2049
2050                if (ret == CY_AS_ERROR_SUCCESS)
2051                        ret = dev_p->storage_error;
2052        }
2053
2054        return ret;
2055}
2056
2057cy_as_return_status_t
2058cy_as_storage_read(cy_as_device_handle handle,
2059        cy_as_bus_number_t bus, uint32_t device,
2060        uint32_t unit, uint32_t block,
2061        void *data_p, uint16_t num_blocks)
2062{
2063        cy_as_device *dev_p = (cy_as_device *)handle;
2064
2065        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2066                return CY_AS_ERROR_INVALID_HANDLE;
2067
2068        return cy_as_storage_sync_oper(dev_p, dev_p->storage_read_endpoint,
2069                CY_RQT_READ_BLOCK, bus, device,
2070                unit, block, data_p, num_blocks);
2071}
2072
2073cy_as_return_status_t
2074cy_as_storage_write(cy_as_device_handle handle,
2075        cy_as_bus_number_t bus, uint32_t device,
2076        uint32_t unit, uint32_t block, void *data_p,
2077        uint16_t num_blocks)
2078{
2079        cy_as_device *dev_p = (cy_as_device *)handle;
2080
2081        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2082                return CY_AS_ERROR_INVALID_HANDLE;
2083
2084        if (dev_p->mtp_turbo_active)
2085                return CY_AS_ERROR_NOT_VALID_DURING_MTP;
2086
2087        return cy_as_storage_sync_oper(dev_p,
2088                dev_p->storage_write_endpoint,
2089                CY_RQT_WRITE_BLOCK, bus, device,
2090                unit, block, data_p, num_blocks);
2091}
2092
2093
2094cy_as_return_status_t
2095cy_as_storage_read_async(cy_as_device_handle handle,
2096        cy_as_bus_number_t bus, uint32_t device, uint32_t unit,
2097        uint32_t block, void *data_p, uint16_t num_blocks,
2098        cy_as_storage_callback callback)
2099{
2100        cy_as_device *dev_p = (cy_as_device *)handle;
2101
2102        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2103                return CY_AS_ERROR_INVALID_HANDLE;
2104
2105        if (callback == 0)
2106                return CY_AS_ERROR_NULL_CALLBACK;
2107
2108        return cy_as_storage_async_oper(dev_p,
2109                dev_p->storage_read_endpoint, CY_RQT_READ_BLOCK,
2110                CY_AS_REQUEST_RESPONSE_MS, bus, device, unit,
2111                block, data_p, num_blocks, NULL, callback);
2112}
2113
2114cy_as_return_status_t
2115cy_as_storage_write_async(cy_as_device_handle handle,
2116        cy_as_bus_number_t bus, uint32_t device, uint32_t unit,
2117        uint32_t block, void *data_p, uint16_t num_blocks,
2118        cy_as_storage_callback callback)
2119{
2120        cy_as_device *dev_p = (cy_as_device *)handle;
2121
2122        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2123                return CY_AS_ERROR_INVALID_HANDLE;
2124
2125        if (callback == 0)
2126                return CY_AS_ERROR_NULL_CALLBACK;
2127
2128        if (dev_p->mtp_turbo_active)
2129                return CY_AS_ERROR_NOT_VALID_DURING_MTP;
2130
2131        return cy_as_storage_async_oper(dev_p,
2132                dev_p->storage_write_endpoint, CY_RQT_WRITE_BLOCK,
2133                CY_AS_REQUEST_RESPONSE_MS, bus, device, unit, block,
2134                data_p, num_blocks, NULL, callback);
2135}
2136
2137
2138static void
2139my_storage_cancel_callback(
2140                cy_as_device *dev_p,
2141                uint8_t context,
2142                cy_as_ll_request_response *rqt,
2143                cy_as_ll_request_response *resp,
2144                cy_as_return_status_t stat)
2145{
2146        (void)context;
2147        (void)stat;
2148
2149        /* Nothing to do here, except free up the
2150         * request and response structures. */
2151        cy_as_ll_destroy_response(dev_p, resp);
2152        cy_as_ll_destroy_request(dev_p, rqt);
2153}
2154
2155
2156cy_as_return_status_t
2157cy_as_storage_cancel_async(cy_as_device_handle handle)
2158{
2159        cy_as_return_status_t ret;
2160        cy_as_ll_request_response *req_p , *reply_p;
2161
2162        cy_as_device *dev_p = (cy_as_device *)handle;
2163        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2164                return CY_AS_ERROR_INVALID_HANDLE;
2165
2166        ret = is_storage_active(dev_p);
2167        if (ret != CY_AS_ERROR_SUCCESS)
2168                return ret;
2169
2170        if (!cy_as_device_is_storage_async_pending(dev_p))
2171                return CY_AS_ERROR_ASYNC_NOT_PENDING;
2172
2173        /*
2174         * create and send a mailbox request to firmware
2175         * asking it to abort processing of the current
2176         * P2S operation. the rest of the cancel processing will be
2177         * driven through the callbacks for the read/write call.
2178         */
2179        req_p = cy_as_ll_create_request(dev_p, CY_RQT_ABORT_P2S_XFER,
2180                CY_RQT_GENERAL_RQT_CONTEXT, 1);
2181        if (req_p == 0)
2182                return CY_AS_ERROR_OUT_OF_MEMORY;
2183
2184        reply_p = cy_as_ll_create_response(dev_p, 1);
2185        if (reply_p == 0) {
2186                cy_as_ll_destroy_request(dev_p, req_p);
2187                return CY_AS_ERROR_OUT_OF_MEMORY;
2188        }
2189
2190        ret = cy_as_ll_send_request(dev_p, req_p,
2191                reply_p, cy_false, my_storage_cancel_callback);
2192        if (ret) {
2193                cy_as_ll_destroy_request(dev_p, req_p);
2194                cy_as_ll_destroy_response(dev_p, reply_p);
2195        }
2196
2197        return CY_AS_ERROR_SUCCESS;
2198}
2199
2200/*
2201 * This function does all the API side clean-up associated with
2202 * CyAsStorageStop, without any communication with the firmware.
2203 */
2204void cy_as_storage_cleanup(cy_as_device *dev_p)
2205{
2206        if (dev_p->storage_count) {
2207                cy_as_ll_destroy_request(dev_p, dev_p->storage_rw_req_p);
2208                cy_as_ll_destroy_response(dev_p, dev_p->storage_rw_resp_p);
2209                dev_p->storage_count = 0;
2210                cy_as_device_clear_scsi_messages(dev_p);
2211                cy_as_hal_mem_set(dev_p->storage_device_info,
2212                        0, sizeof(dev_p->storage_device_info));
2213
2214                cy_as_device_clear_storage_async_pending(dev_p);
2215                dev_p->storage_cb = 0;
2216                dev_p->storage_cb_ms = 0;
2217                dev_p->storage_wait = cy_false;
2218        }
2219}
2220
2221static cy_as_return_status_t
2222my_handle_response_sd_reg_read(
2223                cy_as_device                       *dev_p,
2224                cy_as_ll_request_response       *req_p,
2225                cy_as_ll_request_response       *reply_p,
2226                cy_as_storage_sd_reg_read_data *info)
2227{
2228        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2229        uint8_t  resp_type, i;
2230        uint16_t resp_len;
2231        uint8_t  length = info->length;
2232        uint8_t *data_p = info->buf_p;
2233
2234        resp_type = cy_as_ll_request_response__get_code(reply_p);
2235        if (resp_type == CY_RESP_SD_REGISTER_DATA) {
2236                uint16_t *resp_p = reply_p->data + 1;
2237                uint16_t temp;
2238
2239                resp_len = cy_as_ll_request_response__get_word(reply_p, 0);
2240                cy_as_hal_assert(resp_len >= length);
2241
2242                /*
2243                 * copy the values into the output buffer after doing the
2244                 * necessary bit shifting. the bit shifting is required because
2245                 * the data comes out of the west bridge with a 6 bit offset.
2246                 */
2247                i = 0;
2248                while (length) {
2249                        temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10));
2250                        i++;
2251
2252                        *data_p++ = (uint8_t)(temp >> 8);
2253                        length--;
2254
2255                        if (length) {
2256                                *data_p++ = (uint8_t)(temp & 0xFF);
2257                                length--;
2258                        }
2259                }
2260        } else {
2261                if (resp_type == CY_RESP_SUCCESS_FAILURE)
2262                        ret = cy_as_ll_request_response__get_word(reply_p, 0);
2263                else
2264                        ret = CY_AS_ERROR_INVALID_RESPONSE;
2265        }
2266
2267        cy_as_ll_destroy_response(dev_p, reply_p);
2268        cy_as_ll_destroy_request(dev_p, req_p);
2269
2270        return ret;
2271}
2272
2273cy_as_return_status_t
2274cy_as_storage_sd_register_read(
2275                cy_as_device_handle               handle,
2276                cy_as_bus_number_t                 bus,
2277                uint8_t                            device,
2278                cy_as_sd_card_reg_type           reg_type,
2279                cy_as_storage_sd_reg_read_data *data_p,
2280                cy_as_function_callback   cb,
2281                uint32_t                                  client)
2282{
2283        cy_as_ll_request_response *req_p , *reply_p;
2284        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2285        uint8_t  length;
2286
2287        /*
2288         * sanity checks required before sending the request to the
2289         * firmware.
2290         */
2291        cy_as_device *dev_p = (cy_as_device *)handle;
2292        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2293                return CY_AS_ERROR_INVALID_HANDLE;
2294
2295        ret = is_storage_active(dev_p);
2296        if (ret != CY_AS_ERROR_SUCCESS)
2297                return ret;
2298
2299        if (device >= CY_AS_MAX_STORAGE_DEVICES)
2300                return CY_AS_ERROR_NO_SUCH_DEVICE;
2301
2302        if (reg_type > cy_as_sd_reg_CSD)
2303                return CY_AS_ERROR_INVALID_PARAMETER;
2304
2305        /* If SD/MMC media is not supported on the
2306         * addressed bus, return error. */
2307        if ((dev_p->media_supported[bus] & (1 << cy_as_media_sd_flash)) == 0)
2308                return CY_AS_ERROR_INVALID_PARAMETER;
2309
2310        /*
2311         * find the amount of data to be returned. this will be the minimum of
2312         * the actual data length, and the length requested.
2313         */
2314        switch (reg_type) {
2315        case cy_as_sd_reg_OCR:
2316                length = CY_AS_SD_REG_OCR_LENGTH;
2317                break;
2318        case cy_as_sd_reg_CID:
2319                length = CY_AS_SD_REG_CID_LENGTH;
2320                break;
2321        case cy_as_sd_reg_CSD:
2322                length = CY_AS_SD_REG_CSD_LENGTH;
2323                break;
2324
2325        default:
2326                length = 0;
2327                cy_as_hal_assert(0);
2328        }
2329
2330        if (length < data_p->length)
2331                data_p->length = length;
2332        length = data_p->length;
2333
2334        /* Create the request to send to the West Bridge device */
2335        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SD_REGISTER_READ,
2336                CY_RQT_STORAGE_RQT_CONTEXT, 1);
2337        if (req_p == 0)
2338                return CY_AS_ERROR_OUT_OF_MEMORY;
2339
2340        cy_as_ll_request_response__set_word(req_p, 0,
2341                (create_address(bus, device, 0) | (uint16_t)reg_type));
2342
2343        reply_p = cy_as_ll_create_response(dev_p,
2344                CY_AS_SD_REG_MAX_RESP_LENGTH);
2345        if (reply_p == 0) {
2346                cy_as_ll_destroy_request(dev_p, req_p);
2347                return CY_AS_ERROR_OUT_OF_MEMORY;
2348        }
2349
2350        if (cb == 0) {
2351                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2352                if (ret != CY_AS_ERROR_SUCCESS)
2353                        goto destroy;
2354
2355                return my_handle_response_sd_reg_read(dev_p,
2356                        req_p, reply_p, data_p);
2357        } else {
2358                ret = cy_as_misc_send_request(dev_p, cb, client,
2359                        CY_FUNCT_CB_STOR_SDREGISTERREAD, data_p,
2360                        dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
2361                        req_p, reply_p, cy_as_storage_func_callback);
2362
2363                if (ret != CY_AS_ERROR_SUCCESS)
2364                        goto destroy;
2365
2366                /* The request and response are freed as part of the
2367                 * MiscFuncCallback */
2368                return ret;
2369        }
2370
2371destroy:
2372        cy_as_ll_destroy_request(dev_p, req_p);
2373        cy_as_ll_destroy_response(dev_p, reply_p);
2374
2375        return ret;
2376}
2377
2378cy_as_return_status_t
2379cy_as_storage_create_p_partition(
2380                /* Handle to the device of interest */
2381                cy_as_device_handle             handle,
2382                cy_as_bus_number_t               bus,
2383                uint32_t                                device,
2384                /* of P-port only partition in blocks */
2385                uint32_t                                size,
2386                cy_as_function_callback cb,
2387                uint32_t                                client)
2388{
2389        cy_as_ll_request_response *req_p, *reply_p;
2390        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2391        cy_as_device *dev_p = (cy_as_device *)handle;
2392
2393        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2394                return CY_AS_ERROR_INVALID_HANDLE;
2395
2396        ret = is_storage_active(dev_p);
2397        if (ret != CY_AS_ERROR_SUCCESS)
2398                return ret;
2399
2400        /* Partitions cannot be created or deleted while
2401         * the USB stack is active. */
2402        if (dev_p->usb_count)
2403                return CY_AS_ERROR_USB_RUNNING;
2404
2405        /* Create the request to send to the West Bridge device */
2406        req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_STORAGE,
2407                CY_RQT_STORAGE_RQT_CONTEXT, 3);
2408
2409        if (req_p == 0)
2410                return CY_AS_ERROR_OUT_OF_MEMORY;
2411
2412        /* Reserve space for the reply, the reply
2413         * data will not exceed one word */
2414        reply_p = cy_as_ll_create_response(dev_p, 1);
2415        if (reply_p == 0) {
2416                cy_as_ll_destroy_request(dev_p, req_p);
2417                return CY_AS_ERROR_OUT_OF_MEMORY;
2418        }
2419        cy_as_ll_request_response__set_word(req_p, 0,
2420                create_address(bus, (uint8_t)device, 0x00));
2421        cy_as_ll_request_response__set_word(req_p, 1,
2422                (uint16_t)((size >> 16) & 0xffff));
2423        cy_as_ll_request_response__set_word(req_p, 2,
2424                (uint16_t)(size & 0xffff));
2425
2426        if (cb == 0) {
2427                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2428                if (ret != CY_AS_ERROR_SUCCESS)
2429                        goto destroy;
2430
2431                return my_handle_response_no_data(dev_p, req_p, reply_p);
2432        } else {
2433                ret = cy_as_misc_send_request(dev_p, cb, client,
2434                        CY_FUNCT_CB_STOR_PARTITION, 0, dev_p->func_cbs_stor,
2435                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
2436                        cy_as_storage_func_callback);
2437
2438                if (ret != CY_AS_ERROR_SUCCESS)
2439                        goto destroy;
2440
2441                /* The request and response are freed as part of the
2442                 * FuncCallback */
2443                return ret;
2444
2445        }
2446
2447destroy:
2448        cy_as_ll_destroy_request(dev_p, req_p);
2449        cy_as_ll_destroy_response(dev_p, reply_p);
2450
2451        return ret;
2452}
2453
2454cy_as_return_status_t
2455cy_as_storage_remove_p_partition(
2456                cy_as_device_handle             handle,
2457                cy_as_bus_number_t               bus,
2458                uint32_t                                device,
2459                cy_as_function_callback cb,
2460                uint32_t                                client)
2461{
2462        cy_as_ll_request_response *req_p, *reply_p;
2463        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2464        cy_as_device *dev_p = (cy_as_device *)handle;
2465
2466        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2467                return CY_AS_ERROR_INVALID_HANDLE;
2468
2469        ret = is_storage_active(dev_p);
2470        if (ret != CY_AS_ERROR_SUCCESS)
2471                return ret;
2472
2473        /* Partitions cannot be created or deleted while
2474         * the USB stack is active. */
2475        if (dev_p->usb_count)
2476                return CY_AS_ERROR_USB_RUNNING;
2477
2478        /* Create the request to send to the West Bridge device */
2479        req_p = cy_as_ll_create_request(dev_p, CY_RQT_PARTITION_ERASE,
2480                CY_RQT_STORAGE_RQT_CONTEXT, 1);
2481        if (req_p == 0)
2482                return CY_AS_ERROR_OUT_OF_MEMORY;
2483
2484        /* Reserve space for the reply, the reply
2485         * data will not exceed one word */
2486        reply_p = cy_as_ll_create_response(dev_p, 1);
2487        if (reply_p == 0) {
2488                cy_as_ll_destroy_request(dev_p, req_p);
2489                return CY_AS_ERROR_OUT_OF_MEMORY;
2490        }
2491
2492        cy_as_ll_request_response__set_word(req_p,
2493                0, create_address(bus, (uint8_t)device, 0x00));
2494
2495        if (cb == 0) {
2496                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2497                if (ret != CY_AS_ERROR_SUCCESS)
2498                        goto destroy;
2499
2500                return my_handle_response_no_data(dev_p, req_p, reply_p);
2501        } else {
2502                ret = cy_as_misc_send_request(dev_p, cb, client,
2503                        CY_FUNCT_CB_NODATA, 0, dev_p->func_cbs_stor,
2504                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
2505                        cy_as_storage_func_callback);
2506
2507                if (ret != CY_AS_ERROR_SUCCESS)
2508                        goto destroy;
2509
2510                /* The request and response are freed
2511                 * as part of the FuncCallback */
2512                return ret;
2513
2514        }
2515
2516destroy:
2517        cy_as_ll_destroy_request(dev_p, req_p);
2518        cy_as_ll_destroy_response(dev_p, reply_p);
2519
2520        return ret;
2521}
2522
2523static cy_as_return_status_t
2524my_handle_response_get_transfer_amount(cy_as_device *dev_p,
2525                                cy_as_ll_request_response *req_p,
2526                                cy_as_ll_request_response *reply_p,
2527                                cy_as_m_s_c_progress_data *data)
2528{
2529        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2530        uint8_t code = cy_as_ll_request_response__get_code(reply_p);
2531        uint16_t v1, v2;
2532
2533        if (code != CY_RESP_TRANSFER_COUNT) {
2534                ret = CY_AS_ERROR_INVALID_RESPONSE;
2535                goto destroy;
2536        }
2537
2538        v1 = cy_as_ll_request_response__get_word(reply_p, 0);
2539        v2 = cy_as_ll_request_response__get_word(reply_p, 1);
2540        data->wr_count = (uint32_t)((v1 << 16) | v2);
2541
2542        v1 = cy_as_ll_request_response__get_word(reply_p, 2);
2543        v2 = cy_as_ll_request_response__get_word(reply_p, 3);
2544        data->rd_count = (uint32_t)((v1 << 16) | v2);
2545
2546destroy:
2547        cy_as_ll_destroy_request(dev_p, req_p);
2548        cy_as_ll_destroy_response(dev_p, reply_p);
2549
2550        return ret;
2551}
2552
2553cy_as_return_status_t
2554cy_as_storage_get_transfer_amount(
2555                cy_as_device_handle handle,
2556                cy_as_bus_number_t  bus,
2557                uint32_t device,
2558                cy_as_m_s_c_progress_data *data_p,
2559                cy_as_function_callback cb,
2560                uint32_t client
2561        )
2562{
2563        cy_as_ll_request_response *req_p, *reply_p;
2564        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2565        cy_as_device *dev_p = (cy_as_device *)handle;
2566
2567        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2568                return CY_AS_ERROR_INVALID_HANDLE;
2569
2570        ret = is_storage_active(dev_p);
2571        if (ret != CY_AS_ERROR_SUCCESS)
2572                return ret;
2573
2574        /* Check if the firmware image supports this feature. */
2575        if ((dev_p->media_supported[0]) && (dev_p->media_supported[0]
2576        == (1 << cy_as_media_nand)))
2577                return CY_AS_ERROR_NOT_SUPPORTED;
2578
2579        /* Create the request to send to the West Bridge device */
2580        req_p = cy_as_ll_create_request(dev_p, CY_RQT_GET_TRANSFER_AMOUNT,
2581                CY_RQT_STORAGE_RQT_CONTEXT, 1);
2582        if (req_p == 0)
2583                return CY_AS_ERROR_OUT_OF_MEMORY;
2584
2585        /* Reserve space for the reply, the reply data
2586         * will not exceed four words. */
2587        reply_p = cy_as_ll_create_response(dev_p, 4);
2588        if (reply_p == 0) {
2589                cy_as_ll_destroy_request(dev_p, req_p);
2590                return CY_AS_ERROR_OUT_OF_MEMORY;
2591        }
2592
2593        cy_as_ll_request_response__set_word(req_p, 0,
2594                create_address(bus, (uint8_t)device, 0x00));
2595
2596        if (cb == 0) {
2597                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2598                if (ret != CY_AS_ERROR_SUCCESS)
2599                        goto destroy;
2600
2601                return my_handle_response_get_transfer_amount(dev_p,
2602                        req_p, reply_p, data_p);
2603        } else {
2604                ret = cy_as_misc_send_request(dev_p, cb, client,
2605                CY_FUNCT_CB_STOR_GETTRANSFERAMOUNT, (void *)data_p,
2606                dev_p->func_cbs_stor, CY_AS_REQUEST_RESPONSE_EX,
2607                req_p, reply_p, cy_as_storage_func_callback);
2608
2609                if (ret != CY_AS_ERROR_SUCCESS)
2610                        goto destroy;
2611
2612                /* The request and response are freed as part of the
2613                 * FuncCallback */
2614                return ret;
2615        }
2616
2617destroy:
2618        cy_as_ll_destroy_request(dev_p, req_p);
2619        cy_as_ll_destroy_response(dev_p, reply_p);
2620
2621        return ret;
2622
2623}
2624
2625cy_as_return_status_t
2626cy_as_storage_erase(
2627                cy_as_device_handle             handle,
2628                cy_as_bus_number_t               bus,
2629                uint32_t                                device,
2630                uint32_t                                erase_unit,
2631                uint16_t                                num_erase_units,
2632                cy_as_function_callback cb,
2633                uint32_t                                client
2634                )
2635{
2636        cy_as_ll_request_response *req_p, *reply_p;
2637        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2638        cy_as_device *dev_p = (cy_as_device *)handle;
2639
2640        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2641                return CY_AS_ERROR_INVALID_HANDLE;
2642
2643        ret = is_storage_active(dev_p);
2644        if (ret != CY_AS_ERROR_SUCCESS)
2645                return ret;
2646
2647        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
2648                return CY_AS_ERROR_NO_SUCH_BUS;
2649
2650        if (device >= CY_AS_MAX_STORAGE_DEVICES)
2651                return CY_AS_ERROR_NO_SUCH_DEVICE;
2652
2653        if (dev_p->storage_device_info[bus][device].block_size == 0)
2654                return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
2655
2656        /* If SD is not supported on the specified bus, then return ERROR */
2657        if (dev_p->storage_device_info[bus][device].type !=
2658                cy_as_media_sd_flash)
2659                return CY_AS_ERROR_NOT_SUPPORTED;
2660
2661        if (num_erase_units == 0)
2662                return CY_AS_ERROR_SUCCESS;
2663
2664        /* Create the request to send to the West Bridge device */
2665        req_p = cy_as_ll_create_request(dev_p, CY_RQT_ERASE,
2666                CY_RQT_STORAGE_RQT_CONTEXT, 5);
2667
2668        if (req_p == 0)
2669                return CY_AS_ERROR_OUT_OF_MEMORY;
2670
2671        /* Reserve space for the reply, the reply
2672         * data will not exceed four words. */
2673        reply_p = cy_as_ll_create_response(dev_p, 4);
2674        if (reply_p == 0) {
2675                cy_as_ll_destroy_request(dev_p, req_p);
2676                return CY_AS_ERROR_OUT_OF_MEMORY;
2677        }
2678
2679        cy_as_ll_request_response__set_word(req_p, 0,
2680                create_address(bus, (uint8_t)device, 0x00));
2681        cy_as_ll_request_response__set_word(req_p, 1,
2682                (uint16_t)((erase_unit >> 16) & 0xffff));
2683        cy_as_ll_request_response__set_word(req_p, 2,
2684                (uint16_t)(erase_unit & 0xffff));
2685        cy_as_ll_request_response__set_word(req_p, 3,
2686                (uint16_t)((num_erase_units >> 8) & 0x00ff));
2687        cy_as_ll_request_response__set_word(req_p, 4,
2688                (uint16_t)((num_erase_units << 8) & 0xff00));
2689
2690        if (cb == 0) {
2691                ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2692                if (ret != CY_AS_ERROR_SUCCESS)
2693                        goto destroy;
2694
2695                ret = my_handle_response_no_data(dev_p, req_p, reply_p);
2696
2697                /* If error = "invalid response", this (very likely) means
2698                 * that we are not using the SD-only firmware module which
2699                 * is the only one supporting storage_erase. in this case
2700                 * force a "non supported" error code */
2701                if (ret == CY_AS_ERROR_INVALID_RESPONSE)
2702                        ret = CY_AS_ERROR_NOT_SUPPORTED;
2703
2704                return ret;
2705        } else {
2706                ret = cy_as_misc_send_request(dev_p, cb, client,
2707                        CY_FUNCT_CB_STOR_ERASE, 0, dev_p->func_cbs_stor,
2708                        CY_AS_REQUEST_RESPONSE_EX, req_p, reply_p,
2709                        cy_as_storage_func_callback);
2710
2711                if (ret != CY_AS_ERROR_SUCCESS)
2712                        goto destroy;
2713
2714                /* The request and response are freed
2715                 * as part of the FuncCallback */
2716                return ret;
2717        }
2718
2719destroy:
2720        cy_as_ll_destroy_request(dev_p, req_p);
2721        cy_as_ll_destroy_response(dev_p, reply_p);
2722
2723        return ret;
2724}
2725
2726static void
2727cy_as_storage_func_callback(cy_as_device *dev_p,
2728                                                uint8_t context,
2729                                                cy_as_ll_request_response *rqt,
2730                                                cy_as_ll_request_response *resp,
2731                                                cy_as_return_status_t stat)
2732{
2733        cy_as_func_c_b_node *node = (cy_as_func_c_b_node *)
2734                dev_p->func_cbs_stor->head_p;
2735        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2736
2737        cy_bool ex_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_EX)
2738                        == CY_AS_REQUEST_RESPONSE_EX;
2739        cy_bool ms_request = (rqt->flags & CY_AS_REQUEST_RESPONSE_MS)
2740                        == CY_AS_REQUEST_RESPONSE_MS;
2741        uint8_t code;
2742        uint8_t cntxt;
2743
2744        cy_as_hal_assert(ex_request || ms_request);
2745        cy_as_hal_assert(dev_p->func_cbs_stor->count != 0);
2746        cy_as_hal_assert(dev_p->func_cbs_stor->type == CYAS_FUNC_CB);
2747        (void) ex_request;
2748        (void) ms_request;
2749
2750        (void)context;
2751
2752        cntxt = cy_as_ll_request_response__get_context(rqt);
2753        cy_as_hal_assert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT);
2754
2755        code = cy_as_ll_request_response__get_code(rqt);
2756        switch (code) {
2757        case CY_RQT_START_STORAGE:
2758                ret = my_handle_response_storage_start(dev_p, rqt, resp, stat);
2759                break;
2760        case CY_RQT_STOP_STORAGE:
2761                ret = my_handle_response_storage_stop(dev_p, rqt, resp, stat);
2762                break;
2763        case CY_RQT_CLAIM_STORAGE:
2764                ret = my_handle_response_storage_claim(dev_p, rqt, resp);
2765                break;
2766        case CY_RQT_RELEASE_STORAGE:
2767                ret = my_handle_response_storage_release(dev_p, rqt, resp);
2768                break;
2769        case CY_RQT_QUERY_MEDIA:
2770                cy_as_hal_assert(cy_false);/* Not used any more. */
2771                break;
2772        case CY_RQT_QUERY_BUS:
2773                cy_as_hal_assert(node->data != 0);
2774                ret = my_handle_response_storage_query_bus(dev_p,
2775                        rqt, resp, (uint32_t *)node->data);
2776                break;
2777        case CY_RQT_QUERY_DEVICE:
2778                cy_as_hal_assert(node->data != 0);
2779                ret = my_handle_response_storage_query_device(dev_p,
2780                        rqt, resp, node->data);
2781                break;
2782        case CY_RQT_QUERY_UNIT:
2783                cy_as_hal_assert(node->data != 0);
2784                ret = my_handle_response_storage_query_unit(dev_p,
2785                        rqt, resp, node->data);
2786                break;
2787        case CY_RQT_SD_INTERFACE_CONTROL:
2788                ret = my_handle_response_no_data(dev_p, rqt, resp);
2789                break;
2790        case CY_RQT_SD_REGISTER_READ:
2791                cy_as_hal_assert(node->data != 0);
2792                ret = my_handle_response_sd_reg_read(dev_p, rqt, resp,
2793                        (cy_as_storage_sd_reg_read_data *)node->data);
2794                break;
2795        case CY_RQT_PARTITION_STORAGE:
2796                ret = my_handle_response_no_data(dev_p, rqt, resp);
2797                break;
2798        case CY_RQT_PARTITION_ERASE:
2799                ret = my_handle_response_no_data(dev_p, rqt, resp);
2800                break;
2801        case CY_RQT_GET_TRANSFER_AMOUNT:
2802                cy_as_hal_assert(node->data != 0);
2803                ret = my_handle_response_get_transfer_amount(dev_p,
2804                        rqt, resp, (cy_as_m_s_c_progress_data *)node->data);
2805                break;
2806        case CY_RQT_ERASE:
2807                ret = my_handle_response_no_data(dev_p, rqt, resp);
2808
2809                /* If error = "invalid response", this (very likely)
2810                 * means that we are not using the SD-only firmware
2811                 * module which is the only one supporting storage_erase.
2812                 * in this case force a "non supported" error code */
2813                if (ret == CY_AS_ERROR_INVALID_RESPONSE)
2814                        ret = CY_AS_ERROR_NOT_SUPPORTED;
2815
2816                break;
2817
2818        default:
2819                ret = CY_AS_ERROR_INVALID_RESPONSE;
2820                cy_as_hal_assert(cy_false);
2821                break;
2822        }
2823
2824        /*
2825         * if the low level layer returns a direct error, use the
2826         * corresponding error code. if not, use the error code
2827         * based on the response from firmware.
2828         */
2829        if (stat == CY_AS_ERROR_SUCCESS)
2830                stat = ret;
2831
2832        /* Call the user callback, if there is one */
2833        if (node->cb_p)
2834                node->cb_p((cy_as_device_handle)dev_p, stat,
2835                        node->client_data, node->data_type, node->data);
2836        cy_as_remove_c_b_node(dev_p->func_cbs_stor);
2837}
2838
2839
2840static void
2841cy_as_sdio_sync_reply_callback(
2842                cy_as_device *dev_p,
2843                uint8_t context,
2844                cy_as_ll_request_response *rqt,
2845                cy_as_ll_request_response *resp,
2846                cy_as_return_status_t ret)
2847{
2848        (void)rqt;
2849
2850        if ((cy_as_ll_request_response__get_code(resp) ==
2851        CY_RESP_SDIO_GET_TUPLE) ||
2852        (cy_as_ll_request_response__get_code(resp) ==
2853        CY_RESP_SDIO_EXT)) {
2854                ret = cy_as_ll_request_response__get_word(resp, 0);
2855                if ((ret & 0x00FF) != CY_AS_ERROR_SUCCESS) {
2856                        if (cy_as_ll_request_response__get_code(rqt) ==
2857                        CY_RQT_SDIO_READ_EXTENDED)
2858                                cy_as_dma_cancel(dev_p,
2859                                        dev_p->storage_read_endpoint, ret);
2860                        else
2861                                cy_as_dma_cancel(dev_p,
2862                                        dev_p->storage_write_endpoint, ret);
2863                }
2864        } else {
2865                ret = CY_AS_ERROR_INVALID_RESPONSE;
2866        }
2867
2868        dev_p->storage_rw_resp_p = resp;
2869        dev_p->storage_wait = cy_false;
2870        if (((ret & 0x00FF) == CY_AS_ERROR_IO_ABORTED) || ((ret & 0x00FF)
2871        == CY_AS_ERROR_IO_SUSPENDED))
2872                dev_p->storage_error =  (ret & 0x00FF);
2873        else
2874                dev_p->storage_error = (ret & 0x00FF) ?
2875                CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS;
2876
2877        /* Wake any threads/processes that are waiting on
2878         * the read/write completion. */
2879        cy_as_hal_wake(&dev_p->context[context]->channel);
2880}
2881
2882cy_as_return_status_t
2883cy_as_sdio_device_check(
2884                cy_as_device *dev_p,
2885                cy_as_bus_number_t       bus,
2886                uint32_t                        device)
2887{
2888        if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2889                return CY_AS_ERROR_INVALID_HANDLE;
2890
2891        if (bus < 0 || bus >= CY_AS_MAX_BUSES)
2892                return CY_AS_ERROR_NO_SUCH_BUS;
2893
2894        if (device >= CY_AS_MAX_STORAGE_DEVICES)
2895                return CY_AS_ERROR_NO_SUCH_DEVICE;
2896
2897        if (!cy_as_device_is_astoria_dev(dev_p))
2898                return CY_AS_ERROR_NOT_SUPPORTED;
2899
2900        return  (is_storage_active(dev_p));
2901}
2902
2903cy_as_return_status_t
2904cy_as_sdio_direct_io(
2905                cy_as_device_handle     handle,
2906                cy_as_bus_number_t       bus,
2907                uint32_t                        device,
2908                uint8_t                  n_function_no,
2909                uint32_t                        address,
2910                uint8_t                  misc_buf,
2911                uint16_t                        argument,
2912                uint8_t                  is_write,
2913                uint8_t *data_p)
2914{
2915        cy_as_ll_request_response *req_p , *reply_p;
2916        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2917        uint16_t resp_data;
2918
2919        /*
2920         * sanity checks required before sending the request to the
2921         * firmware.
2922         */
2923        cy_as_device *dev_p = (cy_as_device *)handle;
2924        ret = cy_as_sdio_device_check(dev_p, bus, device);
2925        if (ret != CY_AS_ERROR_SUCCESS)
2926                return ret;
2927
2928
2929        if (!(cy_as_sdio_check_function_initialized(handle,
2930                bus, n_function_no)))
2931                return CY_AS_ERROR_INVALID_FUNCTION;
2932        if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
2933                return CY_AS_ERROR_FUNCTION_SUSPENDED;
2934
2935        req_p = cy_as_ll_create_request(dev_p, (is_write == cy_true) ?
2936                CY_RQT_SDIO_WRITE_DIRECT : CY_RQT_SDIO_READ_DIRECT,
2937                        CY_RQT_STORAGE_RQT_CONTEXT, 3);
2938        if (req_p == 0)
2939                return CY_AS_ERROR_OUT_OF_MEMORY;
2940
2941        /*Setting up request*/
2942
2943        cy_as_ll_request_response__set_word(req_p, 0,
2944                create_address(bus, (uint8_t)device, n_function_no));
2945        /* D1 */
2946        if (is_write == cy_true) {
2947                cy_as_ll_request_response__set_word(req_p, 1,
2948                        ((argument<<8) | 0x0080 | (n_function_no<<4) |
2949                        ((misc_buf&CY_SDIO_RAW)<<3) |
2950                        ((misc_buf&CY_SDIO_REARM_INT)>>5) |
2951                        (uint16_t)(address>>15)));
2952        } else {
2953                cy_as_ll_request_response__set_word(req_p, 1,
2954                        (n_function_no<<4) | ((misc_buf&CY_SDIO_REARM_INT)>>5) |
2955                        (uint16_t)(address>>15));
2956        }
2957        /* D2 */
2958        cy_as_ll_request_response__set_word(req_p, 2,
2959                ((uint16_t)((address&0x00007fff)<<1)));
2960
2961        /*Create response*/
2962        reply_p = cy_as_ll_create_response(dev_p, 2);
2963
2964        if (reply_p == 0) {
2965                cy_as_ll_destroy_request(dev_p, req_p);
2966                return CY_AS_ERROR_OUT_OF_MEMORY;
2967        }
2968
2969        /*Sending the request*/
2970        ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2971        if (ret != CY_AS_ERROR_SUCCESS)
2972                goto destroy;
2973
2974        /*Check reply type*/
2975        if (cy_as_ll_request_response__get_code(reply_p) ==
2976        CY_RESP_SDIO_DIRECT) {
2977                resp_data = cy_as_ll_request_response__get_word(reply_p, 0);
2978                if (resp_data >> 8)
2979                        ret = CY_AS_ERROR_INVALID_RESPONSE;
2980                else if (data_p != 0)
2981                        *(uint8_t *)(data_p) = (uint8_t)(resp_data&0x00ff);
2982        } else {
2983                ret = CY_AS_ERROR_INVALID_RESPONSE;
2984        }
2985
2986destroy:
2987        if (req_p != 0)
2988                cy_as_ll_destroy_request(dev_p, req_p);
2989        if (reply_p != 0)
2990                cy_as_ll_destroy_response(dev_p, reply_p);
2991        return ret;
2992}
2993
2994
2995cy_as_return_status_t
2996cy_as_sdio_direct_read(
2997                cy_as_device_handle handle,
2998                cy_as_bus_number_t bus,
2999                uint32_t device,
3000                uint8_t n_function_no,
3001                uint32_t address,
3002                uint8_t misc_buf,
3003                uint8_t *data_p)
3004{
3005        return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
3006                address, misc_buf, 0x00, cy_false, data_p);
3007}
3008
3009cy_as_return_status_t
3010cy_as_sdio_direct_write(
3011                cy_as_device_handle             handle,
3012                cy_as_bus_number_t               bus,
3013                uint32_t                                device,
3014                uint8_t                          n_function_no,
3015                uint32_t                                address,
3016                uint8_t                          misc_buf,
3017                uint16_t                                argument,
3018                uint8_t *data_p)
3019{
3020        return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
3021                address, misc_buf, argument, cy_true, data_p);
3022}
3023
3024/*Cmd53 IO*/
3025cy_as_return_status_t
3026cy_as_sdio_extended_i_o(
3027                cy_as_device_handle             handle,
3028                cy_as_bus_number_t               bus,
3029                uint32_t                                device,
3030                uint8_t                          n_function_no,
3031                uint32_t                                address,
3032                uint8_t                          misc_buf,
3033                uint16_t                                argument,
3034                uint8_t                          is_write,
3035                uint8_t *data_p ,
3036                uint8_t                          is_resume)
3037{
3038        cy_as_ll_request_response *req_p , *reply_p;
3039        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3040        uint8_t resp_type;
3041        uint8_t reqtype;
3042        uint16_t resp_data;
3043        cy_as_context *ctxt_p;
3044        uint32_t  dmasize, loopcount = 200;
3045        cy_as_end_point_number_t ep;
3046
3047        cy_as_device *dev_p = (cy_as_device *)handle;
3048        ret = cy_as_sdio_device_check(dev_p, bus, device);
3049        if (ret != CY_AS_ERROR_SUCCESS)
3050                return ret;
3051
3052        if (!(cy_as_sdio_check_function_initialized(handle,
3053                bus, n_function_no)))
3054                return CY_AS_ERROR_INVALID_FUNCTION;
3055        if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
3056                return CY_AS_ERROR_FUNCTION_SUSPENDED;
3057
3058
3059        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3060        (dev_p->storage_wait))
3061                return CY_AS_ERROR_ASYNC_PENDING;
3062
3063        /* Request for 0 bytes of blocks is returned as a success*/
3064        if (argument == 0)
3065                return CY_AS_ERROR_SUCCESS;
3066
3067        /* Initialise the request to send to the West Bridge device. */
3068        if (is_write == cy_true) {
3069                reqtype = CY_RQT_SDIO_WRITE_EXTENDED;
3070                ep = dev_p->storage_write_endpoint;
3071        } else {
3072                reqtype = CY_RQT_SDIO_READ_EXTENDED;
3073                ep = dev_p->storage_read_endpoint;
3074        }
3075
3076        req_p = dev_p->storage_rw_req_p;
3077        cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3);
3078
3079        /* Initialise the space for reply from the Antioch. */
3080        reply_p = dev_p->storage_rw_resp_p;
3081        cy_as_ll_init_response(reply_p, 2);
3082
3083        /* Setup the DMA request */
3084        if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
3085                if (argument >
3086                        dev_p->sdiocard[bus].
3087                        function[n_function_no-1].blocksize)
3088                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
3089
3090        } else {
3091                if (argument > 511)
3092                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
3093        }
3094
3095        if (argument == 512)
3096                argument = 0;
3097
3098        dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
3099                dev_p->sdiocard[bus].function[n_function_no-1].blocksize
3100                * argument : argument;
3101
3102        ret = cy_as_dma_queue_request(dev_p, ep, (void *)(data_p),
3103                dmasize, cy_false, (is_write & cy_true) ? cy_false :
3104                cy_true, cy_as_sync_storage_callback);
3105
3106        if (ret != CY_AS_ERROR_SUCCESS)
3107                return ret;
3108
3109        cy_as_ll_request_response__set_word(req_p, 0,
3110                create_address(bus, (uint8_t)device,
3111                n_function_no | ((is_resume) ? 0x80 : 0x00)));
3112        cy_as_ll_request_response__set_word(req_p, 1,
3113                ((uint16_t)n_function_no)<<12|
3114                ((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE|CY_SDIO_OP_INCR)))
3115                << 9 | (uint16_t)(address >> 7) |
3116                ((is_write == cy_true) ? 0x8000 : 0x0000));
3117        cy_as_ll_request_response__set_word(req_p, 2,
3118                ((uint16_t)(address&0x0000ffff) << 9) |  argument);
3119
3120
3121        /* Send the request and wait for completion of storage request */
3122        dev_p->storage_wait = cy_true;
3123        ret = cy_as_ll_send_request(dev_p, req_p, reply_p,
3124                cy_true, cy_as_sdio_sync_reply_callback);
3125
3126        if (ret != CY_AS_ERROR_SUCCESS) {
3127                cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
3128        } else {
3129                /* Setup the DMA request */
3130                ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
3131                ret = cy_as_dma_drain_queue(dev_p, ep, cy_true);
3132
3133                while (loopcount-- > 0) {
3134                        if (dev_p->storage_wait == cy_false)
3135                                break;
3136                        cy_as_hal_sleep_on(&ctxt_p->channel, 10);
3137                }
3138                if (dev_p->storage_wait == cy_true) {
3139                        dev_p->storage_wait = cy_false;
3140                        cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
3141                        dev_p->storage_error = CY_AS_ERROR_TIMEOUT;
3142                }
3143
3144                ret = dev_p->storage_error;
3145
3146                if (ret != CY_AS_ERROR_SUCCESS)
3147                        return ret;
3148
3149                resp_type = cy_as_ll_request_response__get_code(
3150                        dev_p->storage_rw_resp_p);
3151                if (resp_type == CY_RESP_SDIO_EXT) {
3152                        resp_data = cy_as_ll_request_response__get_word
3153                                (reply_p, 0)&0x00ff;
3154                        if (resp_data)
3155                                ret = CY_AS_ERROR_INVALID_REQUEST;
3156
3157                } else {
3158                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3159                }
3160        }
3161        return ret;
3162
3163}
3164
3165static void
3166cy_as_sdio_async_reply_callback(
3167                cy_as_device    *dev_p,
3168                uint8_t                          context,
3169                cy_as_ll_request_response *rqt,
3170                cy_as_ll_request_response *resp,
3171                cy_as_return_status_t     ret)
3172{
3173        cy_as_storage_callback cb_ms;
3174        uint8_t reqtype;
3175        uint32_t pendingblocks;
3176        (void)rqt;
3177        (void)context;
3178
3179        pendingblocks = 0;
3180        reqtype = cy_as_ll_request_response__get_code(rqt);
3181        if (ret == CY_AS_ERROR_SUCCESS) {
3182                if ((cy_as_ll_request_response__get_code(resp) ==
3183                CY_RESP_SUCCESS_FAILURE) ||
3184                (cy_as_ll_request_response__get_code(resp) ==
3185                CY_RESP_SDIO_EXT)) {
3186                        ret = cy_as_ll_request_response__get_word(resp, 0);
3187                        ret &= 0x00FF;
3188                } else {
3189                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3190                }
3191        }
3192
3193        if (ret != CY_AS_ERROR_SUCCESS) {
3194                if (reqtype == CY_RQT_SDIO_READ_EXTENDED)
3195                        cy_as_dma_cancel(dev_p,
3196                                dev_p->storage_read_endpoint, ret);
3197                else
3198                        cy_as_dma_cancel(dev_p,
3199                                dev_p->storage_write_endpoint, ret);
3200
3201                dev_p->storage_error = ret;
3202        }
3203
3204        dev_p->storage_wait = cy_false;
3205
3206        /*
3207         * if the DMA callback has already been called,
3208         * the user callback has to be called from here.
3209         */
3210        if (!cy_as_device_is_storage_async_pending(dev_p)) {
3211                cy_as_hal_assert(dev_p->storage_cb_ms != NULL);
3212                cb_ms = dev_p->storage_cb_ms;
3213
3214                dev_p->storage_cb = 0;
3215                dev_p->storage_cb_ms = 0;
3216
3217                if ((ret == CY_AS_ERROR_SUCCESS) ||
3218                (ret == CY_AS_ERROR_IO_ABORTED) ||
3219                (ret == CY_AS_ERROR_IO_SUSPENDED)) {
3220                        ret = dev_p->storage_error;
3221                        pendingblocks = ((uint32_t)
3222                                cy_as_ll_request_response__get_word
3223                                (resp, 1)) << 16;
3224                } else
3225                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3226
3227                cb_ms((cy_as_device_handle)dev_p, dev_p->storage_bus_index,
3228                        dev_p->storage_device_index,
3229                        (dev_p->storage_unit | pendingblocks),
3230                        dev_p->storage_block_addr, dev_p->storage_oper, ret);
3231        } else
3232                dev_p->storage_error = ret;
3233}
3234
3235
3236cy_as_return_status_t
3237cy_as_sdio_extended_i_o_async(
3238                cy_as_device_handle                     handle,
3239                cy_as_bus_number_t                       bus,
3240                uint32_t                                        device,
3241                uint8_t                                  n_function_no,
3242                uint32_t                                        address,
3243                uint8_t                                  misc_buf,
3244                uint16_t                                        argument,
3245                uint8_t                                  is_write,
3246                uint8_t                                 *data_p,
3247                cy_as_storage_callback     callback)
3248{
3249
3250        uint32_t mask;
3251        uint32_t dmasize;
3252        cy_as_ll_request_response *req_p , *reply_p;
3253        uint8_t reqtype;
3254        cy_as_end_point_number_t ep;
3255        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3256        cy_as_device *dev_p = (cy_as_device *)handle;
3257
3258        ret = cy_as_sdio_device_check(dev_p, bus, device);
3259        if (ret != CY_AS_ERROR_SUCCESS)
3260                return ret;
3261
3262        if (!(cy_as_sdio_check_function_initialized(handle,
3263                bus, n_function_no)))
3264                return CY_AS_ERROR_INVALID_FUNCTION;
3265        if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
3266                return CY_AS_ERROR_FUNCTION_SUSPENDED;
3267
3268        if (callback == 0)
3269                return CY_AS_ERROR_NULL_CALLBACK;
3270
3271        /* We are supposed to return sucess if the number of
3272         * blocks is zero
3273         */
3274        if (((misc_buf&CY_SDIO_BLOCKMODE) != 0) && (argument == 0)) {
3275                callback(handle, bus, device, n_function_no, address,
3276                        ((is_write) ? cy_as_op_write : cy_as_op_read),
3277                        CY_AS_ERROR_SUCCESS);
3278                return CY_AS_ERROR_SUCCESS;
3279        }
3280
3281
3282        /*
3283         * since async operations can be triggered by interrupt
3284         * code, we must insure that we do not get multiple async
3285         * operations going at one time and protect this test and
3286         * set operation from interrupts.
3287         */
3288        mask = cy_as_hal_disable_interrupts();
3289        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3290        (dev_p->storage_wait)) {
3291                cy_as_hal_enable_interrupts(mask);
3292                return CY_AS_ERROR_ASYNC_PENDING;
3293        }
3294        cy_as_device_set_storage_async_pending(dev_p);
3295        cy_as_hal_enable_interrupts(mask);
3296
3297
3298        /*
3299         * storage information about the currently
3300         * outstanding request
3301         */
3302        dev_p->storage_cb_ms = callback;
3303        dev_p->storage_bus_index = bus;
3304        dev_p->storage_device_index = device;
3305        dev_p->storage_unit = n_function_no;
3306        dev_p->storage_block_addr = address;
3307
3308        if (is_write == cy_true) {
3309                reqtype = CY_RQT_SDIO_WRITE_EXTENDED;
3310                ep = dev_p->storage_write_endpoint;
3311        } else {
3312                reqtype = CY_RQT_SDIO_READ_EXTENDED;
3313                ep = dev_p->storage_read_endpoint;
3314        }
3315
3316        /* Initialise the request to send to the West Bridge. */
3317        req_p = dev_p->storage_rw_req_p;
3318        cy_as_ll_init_request(req_p, reqtype,
3319                CY_RQT_STORAGE_RQT_CONTEXT, 3);
3320
3321        /* Initialise the space for reply from the West Bridge. */
3322        reply_p = dev_p->storage_rw_resp_p;
3323        cy_as_ll_init_response(reply_p, 2);
3324
3325        if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
3326                if (argument >
3327                dev_p->sdiocard[bus].function[n_function_no-1].blocksize)
3328                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
3329
3330        } else {
3331                if (argument > 511)
3332                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
3333        }
3334
3335        if (argument == 512)
3336                argument = 0;
3337        dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
3338                dev_p->sdiocard[bus].function[n_function_no-1].blocksize *
3339                argument : argument;
3340
3341        /* Setup the DMA request and adjust the storage
3342         * operation if we are reading */
3343        if (reqtype == CY_RQT_SDIO_READ_EXTENDED) {
3344                ret = cy_as_dma_queue_request(dev_p, ep,
3345                        (void *)data_p, dmasize , cy_false, cy_true,
3346                        cy_as_async_storage_callback);
3347                dev_p->storage_oper = cy_as_op_read;
3348        } else if (reqtype == CY_RQT_SDIO_WRITE_EXTENDED) {
3349                ret = cy_as_dma_queue_request(dev_p, ep, (void *)data_p,
3350                dmasize, cy_false, cy_false, cy_as_async_storage_callback);
3351                dev_p->storage_oper = cy_as_op_write;
3352        }
3353
3354        if (ret != CY_AS_ERROR_SUCCESS) {
3355                cy_as_device_clear_storage_async_pending(dev_p);
3356                return ret;
3357        }
3358
3359        cy_as_ll_request_response__set_word(req_p, 0,
3360                create_address(bus, (uint8_t)device, n_function_no));
3361        cy_as_ll_request_response__set_word(req_p, 1,
3362                ((uint16_t)n_function_no) << 12 |
3363                ((uint16_t)(misc_buf & (CY_SDIO_BLOCKMODE | CY_SDIO_OP_INCR)))
3364                << 9 | (uint16_t)(address>>7) |
3365                ((is_write == cy_true) ? 0x8000 : 0x0000));
3366        cy_as_ll_request_response__set_word(req_p, 2,
3367                ((uint16_t)(address&0x0000ffff) << 9) |  argument);
3368
3369
3370        /* Send the request and wait for completion of storage request */
3371        dev_p->storage_wait = cy_true;
3372        ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
3373                cy_as_sdio_async_reply_callback);
3374        if (ret != CY_AS_ERROR_SUCCESS) {
3375                cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
3376                cy_as_device_clear_storage_async_pending(dev_p);
3377        } else {
3378                cy_as_dma_kick_start(dev_p, ep);
3379        }
3380
3381        return ret;
3382}
3383
3384/* CMD53 Extended Read*/
3385cy_as_return_status_t
3386cy_as_sdio_extended_read(
3387                cy_as_device_handle                     handle,
3388                cy_as_bus_number_t                       bus,
3389                uint32_t                                        device,
3390                uint8_t                                  n_function_no,
3391                uint32_t                                        address,
3392                uint8_t                                  misc_buf,
3393                uint16_t                                        argument,
3394                uint8_t                                 *data_p,
3395                cy_as_sdio_callback                     callback)
3396{
3397        if (callback == 0)
3398                return cy_as_sdio_extended_i_o(handle, bus, device,
3399                        n_function_no, address, misc_buf, argument,
3400                        cy_false, data_p, 0);
3401
3402        return cy_as_sdio_extended_i_o_async(handle, bus, device,
3403                n_function_no, address, misc_buf, argument, cy_false,
3404                data_p, callback);
3405}
3406
3407/* CMD53 Extended Write*/
3408cy_as_return_status_t
3409cy_as_sdio_extended_write(
3410                cy_as_device_handle                     handle,
3411                cy_as_bus_number_t                       bus,
3412                uint32_t                                        device,
3413                uint8_t                                  n_function_no,
3414                uint32_t                                        address,
3415                uint8_t                                  misc_buf,
3416                uint16_t                                        argument,
3417                uint8_t                                 *data_p,
3418                cy_as_sdio_callback                     callback)
3419{
3420        if (callback == 0)
3421                return cy_as_sdio_extended_i_o(handle, bus, device,
3422                        n_function_no, address, misc_buf, argument, cy_true,
3423                        data_p, 0);
3424
3425        return cy_as_sdio_extended_i_o_async(handle, bus, device,
3426                n_function_no, address, misc_buf, argument, cy_true,
3427                data_p, callback);
3428}
3429
3430
3431/* Read the CIS info tuples for the given function and Tuple ID*/
3432cy_as_return_status_t
3433cy_as_sdio_get_c_i_s_info(
3434                cy_as_device_handle                     handle,
3435                cy_as_bus_number_t                       bus,
3436                uint32_t                                        device,
3437                uint8_t                                  n_function_no,
3438                uint16_t                                        tuple_id,
3439                uint8_t                                 *data_p)
3440{
3441
3442        cy_as_ll_request_response *req_p , *reply_p;
3443        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3444        uint16_t resp_data;
3445        cy_as_context *ctxt_p;
3446        uint32_t loopcount = 200;
3447
3448        cy_as_device *dev_p = (cy_as_device *)handle;
3449
3450        ret = cy_as_sdio_device_check(dev_p, bus, device);
3451        if (ret != CY_AS_ERROR_SUCCESS)
3452                return ret;
3453
3454        if (!(cy_as_sdio_check_function_initialized(handle, bus, 0)))
3455                return CY_AS_ERROR_INVALID_FUNCTION;
3456
3457        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3458        (dev_p->storage_wait))
3459                return CY_AS_ERROR_ASYNC_PENDING;
3460
3461
3462        /* Initialise the request to send to the Antioch. */
3463        req_p = dev_p->storage_rw_req_p;
3464        cy_as_ll_init_request(req_p, CY_RQT_SDIO_GET_TUPLE,
3465                CY_RQT_STORAGE_RQT_CONTEXT, 2);
3466
3467        /* Initialise the space for reply from the Antioch. */
3468        reply_p = dev_p->storage_rw_resp_p;
3469        cy_as_ll_init_response(reply_p, 3);
3470
3471        /* Setup the DMA request */
3472        ret = cy_as_dma_queue_request(dev_p, dev_p->storage_read_endpoint,
3473                data_p+1, 255, cy_false, cy_true, cy_as_sync_storage_callback);
3474
3475        if (ret != CY_AS_ERROR_SUCCESS)
3476                return ret;
3477
3478        cy_as_ll_request_response__set_word(req_p, 0,
3479                create_address(bus, (uint8_t)device, n_function_no));
3480
3481        /* Set tuple id to fetch. */
3482        cy_as_ll_request_response__set_word(req_p, 1, tuple_id<<8);
3483
3484        /* Send the request and wait for completion of storage request */
3485        dev_p->storage_wait = cy_true;
3486        ret = cy_as_ll_send_request(dev_p, req_p, reply_p, cy_true,
3487                cy_as_sdio_sync_reply_callback);
3488
3489        if (ret != CY_AS_ERROR_SUCCESS) {
3490                cy_as_dma_cancel(dev_p,
3491                        dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED);
3492        } else {
3493                /* Setup the DMA request */
3494                ctxt_p = dev_p->context[CY_RQT_STORAGE_RQT_CONTEXT];
3495                ret = cy_as_dma_drain_queue(dev_p,
3496                        dev_p->storage_read_endpoint, cy_true);
3497
3498                while (loopcount-- > 0) {
3499                        if (dev_p->storage_wait == cy_false)
3500                                break;
3501                        cy_as_hal_sleep_on(&ctxt_p->channel, 10);
3502                }
3503
3504                if (dev_p->storage_wait == cy_true) {
3505                        dev_p->storage_wait = cy_false;
3506                        cy_as_ll_remove_request(dev_p, ctxt_p, req_p, cy_true);
3507                        return CY_AS_ERROR_TIMEOUT;
3508                }
3509                ret = dev_p->storage_error;
3510
3511                if (ret != CY_AS_ERROR_SUCCESS)
3512                        return ret;
3513
3514                if (cy_as_ll_request_response__get_code
3515                (dev_p->storage_rw_resp_p) == CY_RESP_SDIO_GET_TUPLE) {
3516                        resp_data = cy_as_ll_request_response__get_word
3517                                (reply_p, 0);
3518                        if (resp_data) {
3519                                ret = CY_AS_ERROR_INVALID_REQUEST;
3520                        } else if (data_p != 0)
3521                                *(uint8_t *)data_p = (uint8_t)
3522                                        (cy_as_ll_request_response__get_word
3523                                                (reply_p, 0)&0x00ff);
3524                } else {
3525                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3526                }
3527        }
3528        return ret;
3529}
3530
3531/*Query Device*/
3532cy_as_return_status_t
3533cy_as_sdio_query_card(
3534                cy_as_device_handle handle,
3535                cy_as_bus_number_t bus,
3536                uint32_t device,
3537                cy_as_sdio_card *data_p)
3538{
3539        cy_as_ll_request_response *req_p , *reply_p;
3540        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3541
3542        uint8_t resp_type;
3543        cy_as_device *dev_p = (cy_as_device *)handle;
3544
3545        ret = cy_as_sdio_device_check(dev_p, bus, device);
3546        if (ret != CY_AS_ERROR_SUCCESS)
3547                return ret;
3548
3549        /* Allocating memory to the SDIO device structure in dev_p */
3550
3551        cy_as_hal_mem_set(&dev_p->sdiocard[bus], 0, sizeof(cy_as_sdio_device));
3552
3553        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_QUERY_CARD,
3554                CY_RQT_STORAGE_RQT_CONTEXT, 1);
3555        if (req_p == 0)
3556                return CY_AS_ERROR_OUT_OF_MEMORY;
3557
3558        cy_as_ll_request_response__set_word(req_p, 0,
3559                create_address(bus, (uint8_t)device, 0));
3560
3561        reply_p = cy_as_ll_create_response(dev_p, 5);
3562        if (reply_p == 0) {
3563                cy_as_ll_destroy_request(dev_p, req_p);
3564                return CY_AS_ERROR_OUT_OF_MEMORY;
3565        }
3566
3567        ret = cy_as_ll_send_request_wait_reply(dev_p,
3568                req_p, reply_p);
3569
3570        if (ret != CY_AS_ERROR_SUCCESS)
3571                goto destroy;
3572
3573        resp_type = cy_as_ll_request_response__get_code(reply_p);
3574        if (resp_type == CY_RESP_SDIO_QUERY_CARD) {
3575                dev_p->sdiocard[bus].card.num_functions =
3576                        (uint8_t)((reply_p->data[0]&0xff00)>>8);
3577                dev_p->sdiocard[bus].card.memory_present =
3578                        (uint8_t)reply_p->data[0]&0x0001;
3579                dev_p->sdiocard[bus].card.manufacturer__id =
3580                        reply_p->data[1];
3581                dev_p->sdiocard[bus].card.manufacturer_info =
3582                        reply_p->data[2];
3583                dev_p->sdiocard[bus].card.blocksize =
3584                        reply_p->data[3];
3585                dev_p->sdiocard[bus].card.maxblocksize =
3586                        reply_p->data[3];
3587                dev_p->sdiocard[bus].card.card_capability =
3588                        (uint8_t)((reply_p->data[4]&0xff00)>>8);
3589                dev_p->sdiocard[bus].card.sdio_version =
3590                        (uint8_t)(reply_p->data[4]&0x00ff);
3591                dev_p->sdiocard[bus].function_init_map = 0x01;
3592                data_p->num_functions =
3593                        dev_p->sdiocard[bus].card.num_functions;
3594                data_p->memory_present =
3595                        dev_p->sdiocard[bus].card.memory_present;
3596                data_p->manufacturer__id =
3597                        dev_p->sdiocard[bus].card.manufacturer__id;
3598                data_p->manufacturer_info =
3599                        dev_p->sdiocard[bus].card.manufacturer_info;
3600                data_p->blocksize = dev_p->sdiocard[bus].card.blocksize;
3601                data_p->maxblocksize =
3602                        dev_p->sdiocard[bus].card.maxblocksize;
3603                data_p->card_capability =
3604                        dev_p->sdiocard[bus].card.card_capability;
3605                data_p->sdio_version =
3606                        dev_p->sdiocard[bus].card.sdio_version;
3607        } else {
3608                if (resp_type == CY_RESP_SUCCESS_FAILURE)
3609                        ret = cy_as_ll_request_response__get_word(reply_p, 0);
3610                else
3611                        ret = CY_AS_ERROR_INVALID_RESPONSE;
3612        }
3613destroy:
3614        if (req_p != 0)
3615                cy_as_ll_destroy_request(dev_p, req_p);
3616        if (reply_p != 0)
3617                cy_as_ll_destroy_response(dev_p, reply_p);
3618        return ret;
3619}
3620
3621/*Reset SDIO card. */
3622cy_as_return_status_t
3623cy_as_sdio_reset_card(
3624                cy_as_device_handle                     handle,
3625                cy_as_bus_number_t               bus,
3626                uint32_t                                device)
3627{
3628
3629        cy_as_ll_request_response *req_p , *reply_p;
3630        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3631        uint8_t resp_type;
3632        cy_as_device *dev_p = (cy_as_device *)handle;
3633
3634        ret = cy_as_sdio_device_check(dev_p, bus, device);
3635
3636        if (ret != CY_AS_ERROR_SUCCESS)
3637                return ret;
3638
3639        if (dev_p->sdiocard != 0) {
3640                dev_p->sdiocard[bus].function_init_map = 0;
3641                dev_p->sdiocard[bus].function_suspended_map = 0;
3642        }
3643
3644        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_RESET_DEV,
3645                CY_RQT_STORAGE_RQT_CONTEXT, 1);
3646
3647        if (req_p == 0)
3648                return CY_AS_ERROR_OUT_OF_MEMORY;
3649
3650        /*Setup mailbox */
3651        cy_as_ll_request_response__set_word(req_p, 0,
3652                create_address(bus, (uint8_t)device, 0));
3653
3654        reply_p = cy_as_ll_create_response(dev_p, 2);
3655        if (reply_p == 0) {
3656                cy_as_ll_destroy_request(dev_p, req_p);
3657                return CY_AS_ERROR_OUT_OF_MEMORY;
3658        }
3659
3660        ret = cy_as_ll_send_request_wait_reply(dev_p,
3661                req_p, reply_p);
3662
3663        if (ret != CY_AS_ERROR_SUCCESS)
3664                goto destroy;
3665
3666        resp_type = cy_as_ll_request_response__get_code(reply_p);
3667
3668        if (resp_type == CY_RESP_SUCCESS_FAILURE) {
3669                ret = cy_as_ll_request_response__get_word(reply_p, 0);
3670                if (ret == CY_AS_ERROR_SUCCESS)
3671                        ret = cy_as_sdio_query_card(handle, bus, device, 0);
3672        } else
3673                ret = CY_AS_ERROR_INVALID_RESPONSE;
3674
3675destroy:
3676        if (req_p != 0)
3677                cy_as_ll_destroy_request(dev_p, req_p);
3678        if (reply_p != 0)
3679                cy_as_ll_destroy_response(dev_p, reply_p);
3680        return ret;
3681}
3682
3683/* Initialise an IO function*/
3684cy_as_return_status_t
3685cy_as_sdio_init_function(
3686                cy_as_device_handle                     handle,
3687                cy_as_bus_number_t                       bus,
3688                uint32_t                                        device,
3689                uint8_t                                  n_function_no,
3690                uint8_t                                  misc_buf)
3691{
3692        cy_as_ll_request_response *req_p , *reply_p;
3693        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3694        uint8_t resp_type;
3695        cy_as_device *dev_p = (cy_as_device *)handle;
3696
3697        ret = cy_as_sdio_device_check(dev_p, bus, device);
3698
3699        if (ret != CY_AS_ERROR_SUCCESS)
3700                return ret;
3701
3702        if (!(cy_as_sdio_check_function_initialized
3703                (handle, bus, 0)))
3704                return CY_AS_ERROR_NOT_RUNNING;
3705
3706        if ((cy_as_sdio_check_function_initialized
3707        (handle, bus, n_function_no))) {
3708                if (misc_buf&CY_SDIO_FORCE_INIT)
3709                        dev_p->sdiocard[bus].function_init_map &=
3710                                (~(1 << n_function_no));
3711                else
3712                        return CY_AS_ERROR_ALREADY_RUNNING;
3713        }
3714
3715        req_p = cy_as_ll_create_request(dev_p,
3716                CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1);
3717        if (req_p == 0)
3718                return CY_AS_ERROR_OUT_OF_MEMORY;
3719
3720        cy_as_ll_request_response__set_word(req_p, 0,
3721                create_address(bus, (uint8_t)device, n_function_no));
3722
3723        reply_p = cy_as_ll_create_response(dev_p, 5);
3724        if (reply_p == 0) {
3725                cy_as_ll_destroy_request(dev_p, req_p);
3726                return CY_AS_ERROR_OUT_OF_MEMORY;
3727        }
3728
3729        ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3730
3731        if (ret != CY_AS_ERROR_SUCCESS)
3732                goto destroy;
3733
3734        resp_type = cy_as_ll_request_response__get_code(reply_p);
3735
3736        if (resp_type == CY_RESP_SDIO_INIT_FUNCTION) {
3737                dev_p->sdiocard[bus].function[n_function_no-1].function_code =
3738                        (uint8_t)((reply_p->data[0]&0xff00)>>8);
3739                dev_p->sdiocard[bus].function[n_function_no-1].
3740                        extended_func_code = (uint8_t)reply_p->data[0]&0x00ff;
3741                dev_p->sdiocard[bus].function[n_function_no-1].blocksize =
3742                        reply_p->data[1];
3743                dev_p->sdiocard[bus].function[n_function_no-1].
3744                        maxblocksize = reply_p->data[1];
3745                dev_p->sdiocard[bus].function[n_function_no-1].card_psn =
3746                        (uint32_t)(reply_p->data[2])<<16;
3747                dev_p->sdiocard[bus].function[n_function_no-1].card_psn |=
3748                        (uint32_t)(reply_p->data[3]);
3749                dev_p->sdiocard[bus].function[n_function_no-1].csa_bits =
3750                        (uint8_t)((reply_p->data[4]&0xff00)>>8);
3751                dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support =
3752                        (uint8_t)(reply_p->data[4]&0x0001);
3753                dev_p->sdiocard[bus].function_init_map |= (1 << n_function_no);
3754                cy_as_sdio_clear_function_suspended(handle, bus, n_function_no);
3755
3756        } else {
3757                if (resp_type == CY_RESP_SUCCESS_FAILURE)
3758                        ret = cy_as_ll_request_response__get_word(reply_p, 0);
3759                else
3760                        ret = CY_AS_ERROR_INVALID_FUNCTION;
3761        }
3762
3763destroy:
3764        if (req_p != 0)
3765                cy_as_ll_destroy_request(dev_p, req_p);
3766        if (reply_p != 0)
3767                cy_as_ll_destroy_response(dev_p, reply_p);
3768        return ret;
3769}
3770
3771/*Query individual functions. */
3772cy_as_return_status_t
3773cy_as_sdio_query_function(
3774                cy_as_device_handle                     handle,
3775                cy_as_bus_number_t                       bus,
3776                uint32_t                                        device,
3777                uint8_t                                  n_function_no,
3778                cy_as_sdio_func                 *data_p)
3779{
3780        cy_as_device *dev_p = (cy_as_device *)handle;
3781        cy_as_return_status_t ret;
3782
3783        ret = cy_as_sdio_device_check(dev_p, bus, device);
3784        if (ret != CY_AS_ERROR_SUCCESS)
3785                return ret;
3786
3787        if (!(cy_as_sdio_check_function_initialized(handle,
3788                bus, n_function_no)))
3789                return CY_AS_ERROR_INVALID_FUNCTION;
3790
3791        data_p->blocksize =
3792                dev_p->sdiocard[bus].function[n_function_no-1].blocksize;
3793        data_p->card_psn =
3794                dev_p->sdiocard[bus].function[n_function_no-1].card_psn;
3795        data_p->csa_bits =
3796                dev_p->sdiocard[bus].function[n_function_no-1].csa_bits;
3797        data_p->extended_func_code =
3798                dev_p->sdiocard[bus].function[n_function_no-1].
3799                extended_func_code;
3800        data_p->function_code =
3801                dev_p->sdiocard[bus].function[n_function_no-1].function_code;
3802        data_p->maxblocksize =
3803                dev_p->sdiocard[bus].function[n_function_no-1].maxblocksize;
3804        data_p->wakeup_support =
3805                dev_p->sdiocard[bus].function[n_function_no-1].wakeup_support;
3806
3807        return CY_AS_ERROR_SUCCESS;
3808}
3809
3810/* Abort the Current Extended IO Operation*/
3811cy_as_return_status_t
3812cy_as_sdio_abort_function(
3813                cy_as_device_handle                     handle,
3814                cy_as_bus_number_t                       bus,
3815                uint32_t                                        device,
3816                uint8_t                                  n_function_no)
3817{
3818        cy_as_ll_request_response *req_p , *reply_p;
3819        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3820        uint8_t resp_type;
3821        cy_as_device *dev_p = (cy_as_device *)handle;
3822
3823        ret = cy_as_sdio_device_check(dev_p, bus, device);
3824        if (ret != CY_AS_ERROR_SUCCESS)
3825                return ret;
3826
3827        if (!(cy_as_sdio_check_function_initialized(handle,
3828                bus, n_function_no)))
3829                return CY_AS_ERROR_INVALID_FUNCTION;
3830
3831        if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3832        (dev_p->storage_wait)) {
3833                if (!(cy_as_sdio_get_card_capability(handle, bus) &
3834                CY_SDIO_SDC))
3835                        return CY_AS_ERROR_INVALID_COMMAND;
3836        }
3837
3838        req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_ABORT_IO,
3839                CY_RQT_GENERAL_RQT_CONTEXT, 1);
3840
3841        if (req_p == 0)
3842                return CY_AS_ERROR_OUT_OF_MEMORY;
3843
3844        /*Setup mailbox */
3845        cy_as_ll_request_response__set_word(req_p, 0,
3846                create_address(bus, (uint8_t)device, n_function_no));
3847
3848        reply_p = cy_as_ll_create_response(dev_p, 2);
3849        if (reply_p == 0) {
3850                cy_as_ll_destroy_request(dev_p, req_p);
3851                return CY_AS_ERROR_OUT_OF_MEMORY;
3852        }
3853
3854        ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3855        if (ret != CY_AS_ERROR_SUCCESS)
3856                goto destroy;
3857
3858        resp_type = cy_as_ll_request_response__get_code(reply_p);
3859
3860        if (resp_type == CY_RESP_SUCCESS_FAILURE)
3861                ret = cy_as_ll_request_response__get_word(reply_p, 0);
3862        else
3863                ret = CY_AS_ERROR_INVALID_RESPONSE;
3864
3865
3866destroy:
3867        if (req_p != 0)
3868                cy_as_ll_destroy_request(dev_p, req_p);
3869        if (reply_p != 0)
3870                cy_as_ll_destroy_response(dev_p, reply_p);
3871        return ret;
3872}
3873
3874/* Suspend IO to current function*/
3875cy_as_return_status_t
3876cy_as_sdio_suspend(
3877                cy_as_device_handle             handle,
3878                cy_as_bus_number_t               bus,
3879                uint32_t                                device,
3880                uint8_t                          n_function_no)
3881{
3882        cy_as_ll_request_response *req_p , *reply_p;
3883        cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3884        cy_as_device *dev_p = (cy_as_device *)handle;
3885
3886        ret = cy_as_sdio_device_check(dev_p, bus, device);
3887        if (ret != CY_AS_ERROR_SUCCESS)
3888                return ret;
3889
3890        if (!(cy_as_sdio_check_function_initialized(handle, bus,
3891                n_function_no)))
3892                return CY_AS_ERROR_INVALID_FUNCTION;
3893        if (!(cy_as_sdio_check_support_bus_suspend(handle, bus)))
3894                return CY_AS_ERROR_INVALID_FUNCTION;
3895        if (!(cy_as_sdio_get_card_capability(handle, bus) & CY_SDIO_SDC))
3896                return CY_AS_ERROR_INVALID_FUNCTION;
3897        if (cy_as_sdio_check_function_suspended(handle, bus, n_function_no))
3898                return CY_AS_ERROR_FUNCTION_SUSPENDED;
3899
3900        req_p = cy_as_ll_create_request(dev_p,
3901                CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1);
3902        if (req_p == 0)
3903                return CY_AS_ERROR_OUT_OF_MEMORY;
3904
3905        /*Setup mailbox */
3906        cy_as_ll_request_response__set_word(req_p, 0,
3907                create_address(bus, (uint8_t)device, n_function_no));
3908
3909        reply_p = cy_as_ll_create_response(dev_p, 2);
3910        if (reply_p == 0) {
3911                cy_as_ll_destroy_request(dev_p, req_p);
3912                return CY_AS_ERROR_OUT_OF_MEMORY;
3913        }
3914        ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3915
3916        if (ret == CY_AS_ERROR_SUCCESS) {
3917                ret = cy_as_ll_request_response__get_code(reply_p);
3918                cy_as_sdio_set_function_suspended(handle, bus, n_function_no);
3919        }
3920
3921        if (req_p != 0)
3922                cy_as_ll_destroy_request(dev_p, req_p);
3923        if (reply_p != 0)
3924                cy_as_ll_destroy_response(dev_p, reply_p);
3925
3926        return ret;
3927}
3928
3929/*Resume suspended function*/
3930cy_as_return_status_t
3931cy_as_sdio_resume(
3932                cy_as_device_handle             handle,
3933                cy_as_bus_number_t               bus,
3934                uint32_t                                device,
3935                uint8_t                          n_function_no,
3936                cy_as_oper_type                 op,
3937                uint8_t                          misc_buf,
3938                uint16_t                                pendingblockcount,
3939                uint8_t                          *data_p
3940                )
3941{
3942        cy_as_ll_request_response *req_p , *reply_p;
3943        cy_as_return_status_t resp_data, ret = CY_AS_ERROR_SUCCESS;
3944        cy_as_device *dev_p = (cy_as_device *)handle;
3945
3946        ret = cy_as_sdio_device_check(dev_p, bus, device);
3947        if (ret != CY_AS_ERROR_SUCCESS)
3948                return ret;
3949
3950        if (!(cy_as_sdio_check_function_initialized
3951        (handle, bus, n_function_no)))
3952                return CY_AS_ERROR_INVALID_FUNCTION;
3953
3954        /* If suspend resume is not supported return */
3955        if (!(cy_as_sdio_check_support_bus_suspend(handle, bus)))
3956                return CY_AS_ERROR_INVALID_FUNCTION;
3957
3958        /* if the function is not suspended return. */
3959        if (!(cy_as_sdio_check_function_suspended
3960        (handle, bus, n_function_no)))
3961                return CY_AS_ERROR_INVALID_FUNCTION;
3962
3963        req_p = cy_as_ll_create_request(dev_p,
3964                CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1);
3965        if (req_p == 0)
3966                return CY_AS_ERROR_OUT_OF_MEMORY;
3967
3968        /*Setup mailbox */
3969        cy_as_ll_request_response__set_word(req_p, 0,
3970                create_address(bus, (uint8_t)device, n_function_no));
3971
3972        reply_p = cy_as_ll_create_response(dev_p, 2);
3973        if (reply_p == 0) {
3974                cy_as_ll_destroy_request(dev_p, req_p);
3975                return CY_AS_ERROR_OUT_OF_MEMORY;
3976        }
3977        ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3978
3979        if (ret != CY_AS_ERROR_SUCCESS)
3980                goto destroy;
3981
3982        if (cy_as_ll_request_response__get_code(reply_p) ==
3983        CY_RESP_SDIO_RESUME) {
3984                resp_data = cy_as_ll_request_response__get_word(reply_p, 0);
3985                if (resp_data & 0x00ff) {
3986                        /* Send extended read request to resume the read. */
3987                        if (op == cy_as_op_read) {
3988                                ret = cy_as_sdio_extended_i_o(handle, bus,
3989                                        device, n_function_no, 0, misc_buf,
3990                                        pendingblockcount, cy_false, data_p, 1);
3991                        } else {
3992                                ret = cy_as_sdio_extended_i_o(handle, bus,
3993                                        device, n_function_no, 0, misc_buf,
3994                                        pendingblockcount, cy_true, data_p, 1);
3995                        }
3996                } else {
3997                        ret = CY_AS_ERROR_SUCCESS;
3998                }
3999        } else {
4000                ret = CY_AS_ERROR_INVALID_RESPONSE;
4001        }
4002
4003destroy:
4004        cy_as_sdio_clear_function_suspended(handle, bus, n_function_no);
4005        if (req_p != 0)
4006                cy_as_ll_destroy_request(dev_p, req_p);
4007        if (reply_p != 0)
4008                cy_as_ll_destroy_response(dev_p, reply_p);
4009        return ret;
4010
4011}
4012
4013/*Set function blocksize. Size cannot exceed max
4014 * block size for the function*/
4015cy_as_return_status_t
4016cy_as_sdio_set_blocksize(
4017                cy_as_device_handle                     handle,
4018                cy_as_bus_number_t                       bus,
4019                uint32_t                                        device,
4020                uint8_t                                  n_function_no,
4021                uint16_t                                        blocksize)
4022{
4023        cy_as_return_status_t ret;
4024        cy_as_device *dev_p = (cy_as_device *)handle;
4025        ret = cy_as_sdio_device_check(dev_p, bus, device);
4026        if (ret != CY_AS_ERROR_SUCCESS)
4027                return ret;
4028
4029        if (!(cy_as_sdio_check_function_initialized
4030        (handle, bus, n_function_no)))
4031                return CY_AS_ERROR_INVALID_FUNCTION;
4032        if (n_function_no == 0) {
4033                if (blocksize > cy_as_sdio_get_card_max_blocksize(handle, bus))
4034                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
4035                else if (blocksize == cy_as_sdio_get_card_blocksize
4036                        (handle, bus))
4037                        return CY_AS_ERROR_SUCCESS;
4038        } else {
4039                if (blocksize >
4040                        cy_as_sdio_get_function_max_blocksize(handle,
4041                                bus, n_function_no))
4042                        return CY_AS_ERROR_INVALID_BLOCKSIZE;
4043                else if (blocksize ==
4044                        cy_as_sdio_get_function_blocksize(handle,
4045                                bus, n_function_no))
4046                        return CY_AS_ERROR_SUCCESS;
4047        }
4048
4049        ret = cy_as_sdio_direct_write(handle, bus, device, 0,
4050                (uint16_t)(n_function_no << 8) |
4051                0x10, 0, blocksize & 0x00ff, 0);
4052        if (ret != CY_AS_ERROR_SUCCESS)
4053                return ret;
4054
4055        ret = cy_as_sdio_direct_write(handle, bus, device, 0,
4056                (uint16_t)(n_function_no << 8) |
4057                0x11, 0, (blocksize & 0xff00) >> 8, 0);
4058
4059        if (ret != CY_AS_ERROR_SUCCESS)
4060                return ret;
4061
4062        if (n_function_no == 0)
4063                cy_as_sdio_set_card_block_size(handle, bus, blocksize);
4064        else
4065                cy_as_sdio_set_function_block_size(handle,
4066                        bus, n_function_no, blocksize);
4067        return ret;
4068}
4069
4070/* Deinitialize an SDIO function*/
4071cy_as_return_status_t
4072cy_as_sdio_de_init_function(
4073                cy_as_device_handle                     handle,
4074                cy_as_bus_number_t                       bus,
4075                uint32_t                                        device,
4076                uint8_t                                  n_function_no)
4077{
4078        cy_as_return_status_t ret;
4079        uint8_t temp;
4080
4081        if (n_function_no == 0)
4082                return CY_AS_ERROR_INVALID_FUNCTION;
4083
4084        ret = cy_as_sdio_device_check((cy_as_device *)handle, bus, device);
4085        if (ret != CY_AS_ERROR_SUCCESS)
4086                return ret;
4087
4088        if (!(cy_as_sdio_check_function_initialized
4089                (handle, bus, n_function_no)))
4090                return CY_AS_ERROR_SUCCESS;
4091
4092        temp = (uint8_t)(((cy_as_device *)handle)->sdiocard[bus].
4093                function_init_map & (~(1 << n_function_no)));
4094
4095        cy_as_sdio_direct_write(handle, bus, device, 0, 0x02, 0, temp, 0);
4096
4097        ((cy_as_device *)handle)->sdiocard[bus].function_init_map &=
4098                (~(1 << n_function_no));
4099
4100        return CY_AS_ERROR_SUCCESS;
4101}
4102
4103
4104/*[]*/
4105