]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - drivers/staging/westbridge/astoria/api/src/cyasstorage.c
Initial 2.6.37
[mcf548x/linux.git] / drivers / staging / westbridge / astoria / api / src / cyasstorage.c
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 */
42 cy_as_return_status_t
43 cy_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
77 static uint16_t
78 create_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
86 cy_as_media_type
87 cy_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
117 cy_as_bus_number_t
118 cy_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
125 uint32_t
126 cy_as_storage_get_device_from_address(uint16_t v)
127 {
128         return (uint32_t)((v >> 8) & 0x0f);
129 }
130
131 static uint8_t
132 get_unit_from_address(uint16_t v)
133 {
134         return (uint8_t)(v & 0xff);
135 }
136
137 static cy_as_return_status_t
138 cy_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
160 static void
161 my_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
321 static cy_as_return_status_t
322 is_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
339 static void
340 cy_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
346 static cy_as_return_status_t
347 my_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
361 destroy:
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
368 static cy_as_return_status_t
369 my_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
425 destroy:
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
446 cy_as_return_status_t
447 cy_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
512 destroy:
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
527 static cy_as_return_status_t
528 my_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
542 destroy:
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 }
556 cy_as_return_status_t
557 cy_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
622 destroy:
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
636 cy_as_return_status_t
637 cy_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
661 static cy_as_return_status_t
662 my_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
698 destroy:
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
705 static cy_as_return_status_t
706 my_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
764 destroy:
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
771 cy_as_return_status_t
772 cy_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
787 static cy_as_return_status_t
788 my_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
825 destroy:
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
832 static cy_as_return_status_t
833 my_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
892 destroy:
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
899 cy_as_return_status_t
900 cy_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
915 static cy_as_return_status_t
916 my_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
973 destroy:
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
980 cy_as_return_status_t
981 my_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
1043 destroy:
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
1050 cy_as_return_status_t
1051 cy_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
1063 cy_as_return_status_t
1064 cy_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
1090 static cy_as_return_status_t
1091 my_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
1179 destroy:
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
1186 static cy_as_return_status_t
1187 my_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
1245 destroy:
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
1252 cy_as_return_status_t
1253 cy_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
1264 static cy_as_return_status_t
1265 my_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
1347 destroy:
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
1354 static cy_as_return_status_t
1355 my_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
1420 destroy:
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
1427 cy_as_return_status_t
1428 cy_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
1439 static cy_as_return_status_t
1440 cy_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
1497 destroy:
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
1504 cy_as_return_status_t
1505 my_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         }
1596 destroy:
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
1603 cy_as_return_status_t
1604 cy_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
1619 static void
1620 cy_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
1670 static void
1671 cy_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
1745 static cy_as_return_status_t
1746 cy_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
1882 static void
1883 cy_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
1894 static void
1895 cy_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
1932 static cy_as_return_status_t
1933 cy_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
2057 cy_as_return_status_t
2058 cy_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
2073 cy_as_return_status_t
2074 cy_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
2094 cy_as_return_status_t
2095 cy_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
2114 cy_as_return_status_t
2115 cy_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
2138 static void
2139 my_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
2156 cy_as_return_status_t
2157 cy_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  */
2204 void 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
2221 static cy_as_return_status_t
2222 my_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
2273 cy_as_return_status_t
2274 cy_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
2371 destroy:
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
2378 cy_as_return_status_t
2379 cy_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
2447 destroy:
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
2454 cy_as_return_status_t
2455 cy_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
2516 destroy:
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
2523 static cy_as_return_status_t
2524 my_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
2546 destroy:
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
2553 cy_as_return_status_t
2554 cy_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
2617 destroy:
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
2625 cy_as_return_status_t
2626 cy_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
2719 destroy:
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
2726 static void
2727 cy_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
2840 static void
2841 cy_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
2882 cy_as_return_status_t
2883 cy_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
2903 cy_as_return_status_t
2904 cy_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
2986 destroy:
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
2995 cy_as_return_status_t
2996 cy_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
3009 cy_as_return_status_t
3010 cy_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*/
3025 cy_as_return_status_t
3026 cy_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
3165 static void
3166 cy_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
3236 cy_as_return_status_t
3237 cy_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*/
3385 cy_as_return_status_t
3386 cy_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*/
3408 cy_as_return_status_t
3409 cy_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*/
3432 cy_as_return_status_t
3433 cy_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*/
3532 cy_as_return_status_t
3533 cy_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         }
3613 destroy:
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. */
3622 cy_as_return_status_t
3623 cy_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
3675 destroy:
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*/
3684 cy_as_return_status_t
3685 cy_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
3763 destroy:
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. */
3772 cy_as_return_status_t
3773 cy_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*/
3811 cy_as_return_status_t
3812 cy_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
3866 destroy:
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*/
3875 cy_as_return_status_t
3876 cy_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*/
3930 cy_as_return_status_t
3931 cy_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
4003 destroy:
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*/
4015 cy_as_return_status_t
4016 cy_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*/
4071 cy_as_return_status_t
4072 cy_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 /*[]*/