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