1 /* Cypress West Bridge API source file (cyasstorage.c)
2 ## ===========================
3 ## Copyright (C) 2010 Cypress Semiconductor
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.
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.
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 ## ===========================
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.
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"
41 /* Map a pre-V1.2 media type to the V1.2+ bus number */
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)
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;
51 if (!cy_as_device_is_configured(dev_p))
52 return CY_AS_ERROR_NOT_CONFIGURED;
54 if (!cy_as_device_is_firmware_loaded(dev_p))
55 return CY_AS_ERROR_NO_FIRMWARE;
58 if (dev_p->media_supported[0] & code) {
59 if (dev_p->media_supported[1] & code) {
61 * this media type could be supported on multiple
62 * buses. so, report an address resolution error.
64 ret = CY_AS_ERROR_ADDRESS_RESOLUTION_ERROR;
68 if (dev_p->media_supported[1] & code)
71 ret = CY_AS_ERROR_NO_SUCH_MEDIA;
78 create_address(cy_as_bus_number_t bus, uint32_t device, uint8_t unit)
80 cy_as_hal_assert(bus >= 0 && bus < CY_AS_MAX_BUSES);
81 cy_as_hal_assert(device < 16);
83 return (uint16_t)(((uint8_t)bus << 12) | (device << 8) | unit);
87 cy_as_storage_get_media_from_address(uint16_t v)
89 cy_as_media_type media = cy_as_media_max_media_value;
95 media = cy_as_media_nand;
98 media = cy_as_media_sd_flash;
101 media = cy_as_media_mmc_flash;
104 media = cy_as_media_ce_ata;
107 media = cy_as_media_sdio;
118 cy_as_storage_get_bus_from_address(uint16_t v)
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);
126 cy_as_storage_get_device_from_address(uint16_t v)
128 return (uint32_t)((v >> 8) & 0x0f);
132 get_unit_from_address(uint16_t v)
134 return (uint8_t)(v & 0xff);
137 static cy_as_return_status_t
138 cy_as_map_bad_addr(uint16_t val)
140 cy_as_return_status_t ret = CY_AS_ERROR_INVALID_RESPONSE;
144 ret = CY_AS_ERROR_NO_SUCH_BUS;
147 ret = CY_AS_ERROR_NO_SUCH_DEVICE;
150 ret = CY_AS_ERROR_NO_SUCH_UNIT;
153 ret = CY_AS_ERROR_INVALID_BLOCK;
161 my_storage_request_callback(cy_as_device *dev_p,
163 cy_as_ll_request_response *req_p,
164 cy_as_ll_request_response *resp_p,
165 cy_as_return_status_t ret)
169 cy_as_bus_number_t bus;
171 cy_as_device_handle h = (cy_as_device_handle)dev_p;
172 cy_as_dma_end_point *ep_p = NULL;
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);
183 /* Media has either been inserted or removed */
184 addr = cy_as_ll_request_response__get_word(req_p, 0);
186 bus = cy_as_storage_get_bus_from_address(addr);
187 device = cy_as_storage_get_device_from_address(addr);
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]));
193 val = cy_as_ll_request_response__get_word(req_p, 1);
194 if (dev_p->storage_event_cb_ms) {
196 dev_p->storage_event_cb_ms(h, bus,
197 device, cy_as_storage_removed, 0);
199 dev_p->storage_event_cb_ms(h, bus,
200 device, cy_as_storage_inserted, 0);
201 } else if (dev_p->storage_event_cb) {
203 dev_p->storage_event_cb(h, bus,
204 cy_as_storage_removed, 0);
206 dev_p->storage_event_cb(h, bus,
207 cy_as_storage_inserted, 0);
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) {
219 dev_p->storage_event_cb_ms(h, 0, 0,
220 cy_as_storage_antioch, 0);
222 dev_p->storage_event_cb_ms(h, 1, 0,
223 cy_as_storage_antioch, 0);
226 dev_p->storage_event_cb(h,
228 cy_as_storage_antioch, 0);
230 dev_p->storage_event_cb(h,
231 cy_as_media_sd_flash,
232 cy_as_storage_antioch, 0);
234 dev_p->storage_event_cb(h,
235 cy_as_media_mmc_flash,
236 cy_as_storage_antioch, 0);
238 dev_p->storage_event_cb(h,
240 cy_as_storage_antioch, 0);
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) {
251 dev_p->storage_event_cb_ms(h, 0, 0,
252 cy_as_storage_processor, 0);
254 dev_p->storage_event_cb_ms(h, 1, 0,
255 cy_as_storage_processor, 0);
256 } else if (dev_p->storage_event_cb) {
258 dev_p->storage_event_cb(h,
260 cy_as_storage_processor, 0);
262 dev_p->storage_event_cb(h,
263 cy_as_media_sd_flash,
264 cy_as_storage_processor, 0);
266 dev_p->storage_event_cb(h,
267 cy_as_media_mmc_flash,
268 cy_as_storage_processor, 0);
270 dev_p->storage_event_cb(h,
272 cy_as_storage_processor, 0);
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) {
283 dev_p->storage_event_cb_ms(h, 1, 0,
284 cy_as_sdio_interrupt, 0);
286 dev_p->storage_event_cb_ms(h, 0, 0,
287 cy_as_sdio_interrupt, 0);
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);
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);
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);
312 cy_as_hal_print_message("invalid request received "
313 "on storage context\n");
315 cy_as_ll_send_data_response(dev_p, CY_RQT_STORAGE_RQT_CONTEXT,
316 CY_RESP_INVALID_REQUEST, sizeof(val), &val);
321 static cy_as_return_status_t
322 is_storage_active(cy_as_device *dev_p)
324 if (!cy_as_device_is_configured(dev_p))
325 return CY_AS_ERROR_NOT_CONFIGURED;
327 if (!cy_as_device_is_firmware_loaded(dev_p))
328 return CY_AS_ERROR_NO_FIRMWARE;
330 if (dev_p->storage_count == 0)
331 return CY_AS_ERROR_NOT_RUNNING;
333 if (cy_as_device_is_in_suspend_mode(dev_p))
334 return CY_AS_ERROR_IN_SUSPEND;
336 return CY_AS_ERROR_SUCCESS;
340 cy_as_storage_func_callback(cy_as_device *dev_p,
342 cy_as_ll_request_response *rqt,
343 cy_as_ll_request_response *resp,
344 cy_as_return_status_t ret);
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)
351 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
353 if (cy_as_ll_request_response__get_code(reply_p) !=
354 CY_RESP_SUCCESS_FAILURE) {
355 ret = CY_AS_ERROR_INVALID_RESPONSE;
359 ret = cy_as_ll_request_response__get_word(reply_p, 0);
362 cy_as_ll_destroy_request(dev_p, req_p);
363 cy_as_ll_destroy_response(dev_p, reply_p);
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)
374 if (ret != CY_AS_ERROR_SUCCESS)
377 if (cy_as_ll_request_response__get_code(reply_p) !=
378 CY_RESP_SUCCESS_FAILURE) {
379 ret = CY_AS_ERROR_INVALID_RESPONSE;
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;
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)
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)
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)
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)
408 cy_as_ll_register_request_callback(dev_p,
409 CY_RQT_STORAGE_RQT_CONTEXT, my_storage_request_callback);
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;
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;
426 cy_as_ll_destroy_request(dev_p, req_p);
427 cy_as_ll_destroy_response(dev_p, reply_p);
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;
438 dev_p->storage_count++;
441 cy_as_device_clear_s_s_s_pending(dev_p);
446 cy_as_return_status_t
447 cy_as_storage_start(cy_as_device_handle handle,
448 cy_as_function_callback cb,
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;
455 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
456 return CY_AS_ERROR_INVALID_HANDLE;
458 if (!cy_as_device_is_configured(dev_p))
459 return CY_AS_ERROR_NOT_CONFIGURED;
461 if (!cy_as_device_is_firmware_loaded(dev_p))
462 return CY_AS_ERROR_NO_FIRMWARE;
464 if (cy_as_device_is_in_suspend_mode(dev_p))
465 return CY_AS_ERROR_IN_SUSPEND;
467 if (cy_as_device_is_s_s_s_pending(dev_p))
468 return CY_AS_ERROR_STARTSTOP_PENDING;
470 cy_as_device_set_s_s_s_pending(dev_p);
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);
477 cy_as_device_clear_s_s_s_pending(dev_p);
478 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
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;
491 ret = cy_as_ll_send_request_wait_reply(dev_p,
493 if (ret != CY_AS_ERROR_SUCCESS)
496 return my_handle_response_storage_start(dev_p,
497 req_p, reply_p, ret);
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);
504 if (ret != CY_AS_ERROR_SUCCESS)
507 /* The request and response are freed as
508 * part of the FuncCallback */
513 cy_as_ll_destroy_request(dev_p, req_p);
514 cy_as_ll_destroy_response(dev_p, reply_p);
516 dev_p->storage_count++;
518 cb(handle, ret, client, CY_FUNCT_CB_STOR_START, 0);
521 cy_as_device_clear_s_s_s_pending(dev_p);
525 EXPORT_SYMBOL(cy_as_storage_start);
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)
533 if (ret != CY_AS_ERROR_SUCCESS)
536 if (cy_as_ll_request_response__get_code(reply_p) !=
537 CY_RESP_SUCCESS_FAILURE) {
538 ret = CY_AS_ERROR_INVALID_RESPONSE;
543 cy_as_ll_destroy_request(dev_p, req_p);
544 cy_as_ll_destroy_response(dev_p, reply_p);
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--;
552 cy_as_device_clear_s_s_s_pending(dev_p);
556 cy_as_return_status_t
557 cy_as_storage_stop(cy_as_device_handle handle,
558 cy_as_function_callback cb,
561 cy_as_ll_request_response *req_p , *reply_p;
562 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
564 cy_as_device *dev_p = (cy_as_device *)handle;
566 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
567 return CY_AS_ERROR_INVALID_HANDLE;
569 ret = is_storage_active(dev_p);
570 if (ret != CY_AS_ERROR_SUCCESS)
573 if (cy_as_device_is_storage_async_pending(dev_p))
574 return CY_AS_ERROR_ASYNC_PENDING;
576 if (cy_as_device_is_s_s_s_pending(dev_p))
577 return CY_AS_ERROR_STARTSTOP_PENDING;
579 cy_as_device_set_s_s_s_pending(dev_p);
581 if (dev_p->storage_count == 1) {
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);
587 cy_as_device_clear_s_s_s_pending(dev_p);
588 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
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;
601 ret = cy_as_ll_send_request_wait_reply(dev_p,
603 if (ret != CY_AS_ERROR_SUCCESS)
606 return my_handle_response_storage_stop(dev_p,
607 req_p, reply_p, ret);
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);
614 if (ret != CY_AS_ERROR_SUCCESS)
617 /* The request and response are freed
618 * as part of the MiscFuncCallback */
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--;
628 cb(handle, ret, client, CY_FUNCT_CB_STOR_STOP, 0);
631 cy_as_device_clear_s_s_s_pending(dev_p);
635 EXPORT_SYMBOL(cy_as_storage_stop);
637 cy_as_return_status_t
638 cy_as_storage_register_callback(cy_as_device_handle handle,
639 cy_as_storage_event_callback callback)
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;
645 if (!cy_as_device_is_configured(dev_p))
646 return CY_AS_ERROR_NOT_CONFIGURED;
648 if (!cy_as_device_is_firmware_loaded(dev_p))
649 return CY_AS_ERROR_NO_FIRMWARE;
651 if (dev_p->storage_count == 0)
652 return CY_AS_ERROR_NOT_RUNNING;
654 dev_p->storage_event_cb = NULL;
655 dev_p->storage_event_cb_ms = callback;
657 return CY_AS_ERROR_SUCCESS;
659 EXPORT_SYMBOL(cy_as_storage_register_callback);
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)
667 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
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));
676 if (cy_as_ll_request_response__get_code(reply_p) !=
677 CY_RESP_MEDIA_CLAIMED_RELEASED) {
678 ret = CY_AS_ERROR_INVALID_RESPONSE;
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;
696 if (cy_as_ll_request_response__get_word(reply_p, 1) != 1)
697 ret = CY_AS_ERROR_NOT_ACQUIRED;
700 cy_as_ll_destroy_request(dev_p, req_p);
701 cy_as_ll_destroy_response(dev_p, reply_p);
706 static cy_as_return_status_t
707 my_storage_claim(cy_as_device *dev_p,
709 cy_as_bus_number_t bus,
712 cy_as_function_callback cb,
715 cy_as_ll_request_response *req_p , *reply_p;
716 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
718 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
719 return CY_AS_ERROR_INVALID_HANDLE;
721 ret = is_storage_active(dev_p);
722 if (ret != CY_AS_ERROR_SUCCESS)
725 if (dev_p->mtp_count > 0)
726 return CY_AS_ERROR_NOT_VALID_IN_MTP;
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);
732 return CY_AS_ERROR_OUT_OF_MEMORY;
734 cy_as_ll_request_response__set_word(req_p,
735 0, create_address(bus, device, 0));
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);
741 cy_as_ll_destroy_request(dev_p, req_p);
742 return CY_AS_ERROR_OUT_OF_MEMORY;
746 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
747 if (ret != CY_AS_ERROR_SUCCESS)
750 return my_handle_response_storage_claim(dev_p, req_p, reply_p);
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);
757 if (ret != CY_AS_ERROR_SUCCESS)
760 /* The request and response are freed as part of
761 * the MiscFuncCallback */
766 cy_as_ll_destroy_request(dev_p, req_p);
767 cy_as_ll_destroy_response(dev_p, reply_p);
772 cy_as_return_status_t
773 cy_as_storage_claim(cy_as_device_handle handle,
774 cy_as_bus_number_t bus,
776 cy_as_function_callback cb,
779 cy_as_device *dev_p = (cy_as_device *)handle;
781 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
782 return CY_AS_ERROR_NO_SUCH_BUS;
784 return my_storage_claim(dev_p, NULL, bus, device,
785 CY_AS_REQUEST_RESPONSE_MS, cb, client);
787 EXPORT_SYMBOL(cy_as_storage_claim);
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)
794 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
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));
803 if (cy_as_ll_request_response__get_code(reply_p) !=
804 CY_RESP_MEDIA_CLAIMED_RELEASED) {
805 ret = CY_AS_ERROR_INVALID_RESPONSE;
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;
824 if (cy_as_ll_request_response__get_word(reply_p, 1) != 0)
825 ret = CY_AS_ERROR_NOT_RELEASED;
828 cy_as_ll_destroy_request(dev_p, req_p);
829 cy_as_ll_destroy_response(dev_p, reply_p);
834 static cy_as_return_status_t
835 my_storage_release(cy_as_device *dev_p,
837 cy_as_bus_number_t bus,
840 cy_as_function_callback cb,
843 cy_as_ll_request_response *req_p , *reply_p;
844 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
846 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
847 return CY_AS_ERROR_INVALID_HANDLE;
849 ret = is_storage_active(dev_p);
850 if (ret != CY_AS_ERROR_SUCCESS)
853 if (dev_p->mtp_count > 0)
854 return CY_AS_ERROR_NOT_VALID_IN_MTP;
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);
860 return CY_AS_ERROR_OUT_OF_MEMORY;
862 cy_as_ll_request_response__set_word(
863 req_p, 0, create_address(bus, device, 0));
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);
869 cy_as_ll_destroy_request(dev_p, req_p);
870 return CY_AS_ERROR_OUT_OF_MEMORY;
874 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
875 if (ret != CY_AS_ERROR_SUCCESS)
878 return my_handle_response_storage_release(
879 dev_p, req_p, reply_p);
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);
886 if (ret != CY_AS_ERROR_SUCCESS)
889 /* The request and response are freed as
890 * part of the MiscFuncCallback */
895 cy_as_ll_destroy_request(dev_p, req_p);
896 cy_as_ll_destroy_response(dev_p, reply_p);
901 cy_as_return_status_t
902 cy_as_storage_release(cy_as_device_handle handle,
903 cy_as_bus_number_t bus,
905 cy_as_function_callback cb,
908 cy_as_device *dev_p = (cy_as_device *)handle;
910 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
911 return CY_AS_ERROR_NO_SUCH_BUS;
913 return my_storage_release(dev_p, NULL, bus, device,
914 CY_AS_REQUEST_RESPONSE_MS, cb, client);
916 EXPORT_SYMBOL(cy_as_storage_release);
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,
924 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
925 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
928 if (code == CY_RESP_NO_SUCH_ADDRESS) {
929 ret = CY_AS_ERROR_NO_SUCH_BUS;
933 if (code != CY_RESP_BUS_DESCRIPTOR) {
934 ret = CY_AS_ERROR_INVALID_RESPONSE;
939 * verify that the response corresponds to the bus that was queried.
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;
949 v = cy_as_ll_request_response__get_word(reply_p, 1);
950 if (req_p->flags & CY_AS_REQUEST_RESPONSE_MS) {
952 * this request is only for the count of devices
953 * on the bus. there is no need to check the media type.
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.
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);
970 if (queried == found)
977 cy_as_ll_destroy_request(dev_p, req_p);
978 cy_as_ll_destroy_response(dev_p, reply_p);
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,
989 cy_as_function_callback cb,
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;
996 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
997 return CY_AS_ERROR_INVALID_HANDLE;
999 ret = is_storage_active(dev_p);
1000 if (ret != CY_AS_ERROR_SUCCESS)
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);
1007 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
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);
1017 cy_as_ll_destroy_request(dev_p, req_p);
1018 return CY_AS_ERROR_OUT_OF_MEMORY;
1022 ret = cy_as_ll_send_request_wait_reply(dev_p,
1024 if (ret != CY_AS_ERROR_SUCCESS)
1027 req_p->flags |= req_flags;
1028 return my_handle_response_storage_query_bus(dev_p,
1029 req_p, reply_p, count);
1031 if (req_flags == CY_AS_REQUEST_RESPONSE_EX)
1032 cb_type = CY_FUNCT_CB_STOR_QUERYMEDIA;
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);
1038 if (ret != CY_AS_ERROR_SUCCESS)
1041 /* The request and response are freed as part of
1042 * the MiscFuncCallback */
1047 cy_as_ll_destroy_request(dev_p, req_p);
1048 cy_as_ll_destroy_response(dev_p, reply_p);
1053 cy_as_return_status_t
1054 cy_as_storage_query_bus(cy_as_device_handle handle,
1055 cy_as_bus_number_t bus,
1057 cy_as_function_callback cb,
1060 cy_as_device *dev_p = (cy_as_device *)handle;
1062 return my_storage_query_bus(dev_p, bus, cy_as_media_max_media_value,
1063 CY_AS_REQUEST_RESPONSE_MS, count, cb, client);
1065 EXPORT_SYMBOL(cy_as_storage_query_bus);
1067 cy_as_return_status_t
1068 cy_as_storage_query_media(cy_as_device_handle handle,
1069 cy_as_media_type type,
1071 cy_as_function_callback cb,
1074 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1075 cy_as_bus_number_t bus;
1077 cy_as_device *dev_p = (cy_as_device *)handle;
1079 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1080 return CY_AS_ERROR_INVALID_HANDLE;
1082 ret = is_storage_active(dev_p);
1083 if (ret != CY_AS_ERROR_SUCCESS)
1086 ret = cy_an_map_bus_from_media_type(dev_p, type, &bus);
1087 if (ret != CY_AS_ERROR_SUCCESS)
1090 return my_storage_query_bus(dev_p, bus, type, CY_AS_REQUEST_RESPONSE_EX,
1093 EXPORT_SYMBOL(cy_as_storage_query_media);
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,
1101 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1103 cy_as_bus_number_t bus;
1104 cy_as_media_type type;
1109 uint16_t block_size;
1110 uint32_t number_units;
1111 uint32_t number_eus;
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));
1120 if (cy_as_ll_request_response__get_code(reply_p) !=
1121 CY_RESP_DEVICE_DESCRIPTOR) {
1122 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
1132 block_size = cy_as_ll_request_response__get_word(reply_p, 1);
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);
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);
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;
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;
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;
1164 cy_as_storage_query_device_data_dep *store_p =
1165 (cy_as_storage_query_device_data_dep *)data_p;
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;
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;
1185 cy_as_ll_destroy_request(dev_p, req_p);
1186 cy_as_ll_destroy_response(dev_p, reply_p);
1191 static cy_as_return_status_t
1192 my_storage_query_device(cy_as_device *dev_p,
1195 cy_as_bus_number_t bus,
1197 cy_as_function_callback cb,
1200 cy_as_ll_request_response *req_p , *reply_p;
1201 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1203 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1204 return CY_AS_ERROR_INVALID_HANDLE;
1206 ret = is_storage_active(dev_p);
1207 if (ret != CY_AS_ERROR_SUCCESS)
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);
1214 return CY_AS_ERROR_OUT_OF_MEMORY;
1216 cy_as_ll_request_response__set_word(req_p, 0,
1217 create_address(bus, device, 0));
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);
1223 cy_as_ll_destroy_request(dev_p, req_p);
1224 return CY_AS_ERROR_OUT_OF_MEMORY;
1228 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1229 if (ret != CY_AS_ERROR_SUCCESS)
1232 req_p->flags |= req_flags;
1233 return my_handle_response_storage_query_device(dev_p,
1234 req_p, reply_p, data_p);
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);
1242 if (ret != CY_AS_ERROR_SUCCESS)
1245 /* The request and response are freed as part of the
1246 * MiscFuncCallback */
1251 cy_as_ll_destroy_request(dev_p, req_p);
1252 cy_as_ll_destroy_response(dev_p, reply_p);
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,
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);
1268 EXPORT_SYMBOL(cy_as_storage_query_device);
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,
1276 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1277 cy_as_bus_number_t bus;
1280 cy_as_media_type type;
1281 uint16_t block_size;
1282 uint32_t start_block;
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));
1293 if (cy_as_ll_request_response__get_code(reply_p) !=
1294 CY_RESP_UNIT_DESCRIPTOR) {
1295 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
1305 type = cy_as_storage_get_media_from_address(
1306 cy_as_ll_request_response__get_word(reply_p, 1));
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);
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;
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;
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;
1333 cy_as_storage_query_unit_data_dep *store_p =
1334 (cy_as_storage_query_unit_data_dep *)data_p;
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;
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;
1350 dev_p->storage_device_info[bus][device].type = type;
1351 dev_p->storage_device_info[bus][device].block_size = block_size;
1354 cy_as_ll_destroy_request(dev_p, req_p);
1355 cy_as_ll_destroy_response(dev_p, reply_p);
1360 static cy_as_return_status_t
1361 my_storage_query_unit(cy_as_device *dev_p,
1364 cy_as_bus_number_t bus,
1367 cy_as_function_callback cb,
1370 cy_as_ll_request_response *req_p , *reply_p;
1371 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1373 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1374 return CY_AS_ERROR_INVALID_HANDLE;
1376 ret = is_storage_active(dev_p);
1377 if (ret != CY_AS_ERROR_SUCCESS)
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);
1384 return CY_AS_ERROR_OUT_OF_MEMORY;
1387 return CY_AS_ERROR_NO_SUCH_DEVICE;
1390 return CY_AS_ERROR_NO_SUCH_UNIT;
1392 cy_as_ll_request_response__set_word(req_p, 0,
1393 create_address(bus, device, (uint8_t)unit));
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);
1399 cy_as_ll_destroy_request(dev_p, req_p);
1400 return CY_AS_ERROR_OUT_OF_MEMORY;
1404 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1405 if (ret != CY_AS_ERROR_SUCCESS)
1408 req_p->flags |= req_flags;
1409 return my_handle_response_storage_query_unit(dev_p,
1410 req_p, reply_p, data_p);
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);
1418 if (ret != CY_AS_ERROR_SUCCESS)
1421 /* The request and response are freed
1422 * as part of the MiscFuncCallback */
1427 cy_as_ll_destroy_request(dev_p, req_p);
1428 cy_as_ll_destroy_response(dev_p, reply_p);
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,
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);
1443 EXPORT_SYMBOL(cy_as_storage_query_unit);
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,
1449 cy_as_function_callback cb)
1451 cy_as_ll_request_response *req_p , *reply_p;
1452 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
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);
1458 return CY_AS_ERROR_OUT_OF_MEMORY;
1460 cy_as_ll_request_response__set_word(req_p, 0,
1461 create_address(bus, device, 0));
1463 reply_p = cy_as_ll_create_response(dev_p, 4);
1465 cy_as_ll_destroy_request(dev_p, req_p);
1466 return CY_AS_ERROR_OUT_OF_MEMORY;
1470 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1471 if (ret != CY_AS_ERROR_SUCCESS)
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;
1480 if (cy_as_ll_request_response__get_code(reply_p) !=
1481 CY_RESP_DEVICE_DESCRIPTOR) {
1482 ret = CY_AS_ERROR_INVALID_RESPONSE;
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))
1493 ret = CY_AS_ERROR_INVALID_RESPONSE;
1498 dev_p->storage_device_info[bus][device].block_size =
1499 cy_as_ll_request_response__get_word(reply_p, 1);
1501 ret = CY_AS_ERROR_INVALID_REQUEST;
1504 cy_as_ll_destroy_request(dev_p, req_p);
1505 cy_as_ll_destroy_response(dev_p, reply_p);
1510 cy_as_return_status_t
1511 my_storage_device_control(
1512 cy_as_device *dev_p,
1513 cy_as_bus_number_t bus,
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,
1521 cy_as_ll_request_response *req_p , *reply_p;
1522 cy_as_return_status_t ret;
1523 cy_bool use_gpio = cy_false;
1527 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
1528 return CY_AS_ERROR_INVALID_HANDLE;
1530 if (!cy_as_device_is_configured(dev_p))
1531 return CY_AS_ERROR_NOT_CONFIGURED;
1533 if (!cy_as_device_is_firmware_loaded(dev_p))
1534 return CY_AS_ERROR_NO_FIRMWARE;
1536 if (cy_as_device_is_in_suspend_mode(dev_p))
1537 return CY_AS_ERROR_IN_SUSPEND;
1539 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1540 return CY_AS_ERROR_NO_SUCH_BUS;
1542 if (device >= CY_AS_MAX_STORAGE_DEVICES)
1543 return CY_AS_ERROR_NO_SUCH_DEVICE;
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;
1551 if (config_detect == cy_as_storage_detect_GPIO)
1553 else if (config_detect == cy_as_storage_detect_SDAT_3)
1554 use_gpio = cy_false;
1556 return CY_AS_ERROR_INVALID_PARAMETER;
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);
1562 return CY_AS_ERROR_OUT_OF_MEMORY;
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));
1570 reply_p = cy_as_ll_create_response(dev_p, 1);
1572 cy_as_ll_destroy_request(dev_p, req_p);
1573 return CY_AS_ERROR_OUT_OF_MEMORY;
1577 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
1578 if (ret != CY_AS_ERROR_SUCCESS)
1581 if (cy_as_ll_request_response__get_code(reply_p) !=
1582 CY_RESP_SUCCESS_FAILURE) {
1583 ret = CY_AS_ERROR_INVALID_RESPONSE;
1587 ret = cy_as_ll_request_response__get_word(reply_p, 0);
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);
1595 if (ret != CY_AS_ERROR_SUCCESS)
1598 /* The request and response are freed as part of the
1599 * MiscFuncCallback */
1603 cy_as_ll_destroy_request(dev_p, req_p);
1604 cy_as_ll_destroy_response(dev_p, reply_p);
1609 cy_as_return_status_t
1610 cy_as_storage_device_control(cy_as_device_handle handle,
1611 cy_as_bus_number_t bus,
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,
1619 cy_as_device *dev_p = (cy_as_device *)handle;
1621 return my_storage_device_control(dev_p, bus, device, card_detect_en,
1622 write_prot_en, config_detect, cb, client);
1624 EXPORT_SYMBOL(cy_as_storage_device_control);
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)
1631 cy_as_storage_callback_dep cb;
1632 cy_as_storage_callback cb_ms;
1638 cy_as_device_clear_storage_async_pending(dev_p);
1641 * if the LL request callback has already been called,
1642 * the user callback has to be called from here.
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;
1650 dev_p->storage_cb = 0;
1651 dev_p->storage_cb_ms = 0;
1653 if (ret == CY_AS_ERROR_SUCCESS)
1654 ret = dev_p->storage_error;
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);
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);
1674 dev_p->storage_error = ret;
1678 cy_as_async_storage_reply_callback(
1679 cy_as_device *dev_p,
1681 cy_as_ll_request_response *rqt,
1682 cy_as_ll_request_response *resp,
1683 cy_as_return_status_t ret)
1685 cy_as_storage_callback_dep cb;
1686 cy_as_storage_callback cb_ms;
1691 reqtype = cy_as_ll_request_response__get_code(rqt);
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
1698 } else if (cy_as_ll_request_response__get_code(resp) !=
1699 CY_RESP_SUCCESS_FAILURE) {
1700 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
1709 cy_as_dma_cancel(dev_p,
1710 dev_p->storage_write_endpoint, ret);
1713 dev_p->storage_wait = cy_false;
1716 * if the DMA callback has already been called, the
1717 * user callback has to be called from here.
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;
1725 dev_p->storage_cb = 0;
1726 dev_p->storage_cb_ms = 0;
1728 if (ret == CY_AS_ERROR_SUCCESS)
1729 ret = dev_p->storage_error;
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);
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);
1749 dev_p->storage_error = ret;
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)
1760 cy_as_ll_request_response *req_p , *reply_p;
1761 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
1763 ret = is_storage_active(dev_p);
1764 if (ret != CY_AS_ERROR_SUCCESS)
1767 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1768 return CY_AS_ERROR_NO_SUCH_BUS;
1770 if (device >= CY_AS_MAX_STORAGE_DEVICES)
1771 return CY_AS_ERROR_NO_SUCH_DEVICE;
1774 return CY_AS_ERROR_NO_SUCH_UNIT;
1776 /* We are supposed to return sucess if the number of
1779 if (num_blocks == 0) {
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);
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);
1794 return CY_AS_ERROR_SUCCESS;
1797 if (dev_p->storage_device_info[bus][device].block_size == 0)
1798 return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
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
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;
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);
1820 * storage information about the currently outstanding request
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;
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);
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);
1837 /* Remember which version of the API originated the request */
1838 req_p->flags |= req_flags;
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;
1856 if (ret != CY_AS_ERROR_SUCCESS) {
1857 cy_as_device_clear_storage_async_pending(dev_p);
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));
1872 /* Set the burst mode flag. */
1873 if (dev_p->is_storage_only_mode)
1874 req_p->data[4] |= 0x0001;
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);
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)
1898 dev_p->storage_error = err;
1902 cy_as_sync_storage_reply_callback(
1903 cy_as_device *dev_p,
1905 cy_as_ll_request_response *rqt,
1906 cy_as_ll_request_response *resp,
1907 cy_as_return_status_t ret)
1912 reqtype = cy_as_ll_request_response__get_code(rqt);
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;
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);
1923 cy_as_dma_cancel(dev_p,
1924 dev_p->storage_write_endpoint, ret);
1926 } else if (cy_as_ll_request_response__get_code(resp) !=
1927 CY_RESP_SUCCESS_FAILURE) {
1928 ret = CY_AS_ERROR_INVALID_RESPONSE;
1931 dev_p->storage_wait = cy_false;
1932 dev_p->storage_error = ret;
1934 /* Wake any threads/processes that are waiting on
1935 * the read/write completion. */
1936 cy_as_hal_wake(&dev_p->context[context]->channel);
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)
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;
1951 ret = is_storage_active(dev_p);
1952 if (ret != CY_AS_ERROR_SUCCESS)
1955 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
1956 return CY_AS_ERROR_NO_SUCH_BUS;
1958 if (device >= CY_AS_MAX_STORAGE_DEVICES)
1959 return CY_AS_ERROR_NO_SUCH_DEVICE;
1962 return CY_AS_ERROR_NO_SUCH_UNIT;
1964 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
1965 (dev_p->storage_wait))
1966 return CY_AS_ERROR_ASYNC_PENDING;
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;
1972 /* We are supposed to return sucess if the number of
1975 if (num_blocks == 0)
1976 return CY_AS_ERROR_SUCCESS;
1978 if (dev_p->storage_device_info[bus][device].block_size == 0) {
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.
1984 ret = cy_as_get_block_size(dev_p, bus, device, 0);
1985 if (ret != CY_AS_ERROR_SUCCESS)
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);
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);
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;
2015 if (ret != CY_AS_ERROR_SUCCESS)
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));
2029 /* Set the burst mode flag. */
2030 if (dev_p->is_storage_only_mode)
2031 req_p->data[4] |= 0x0001;
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);
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);
2045 while (loopcount-- > 0) {
2046 if (dev_p->storage_wait == cy_false)
2048 cy_as_hal_sleep_on(&ctxt_p->channel, 10);
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;
2057 if (ret == CY_AS_ERROR_SUCCESS)
2058 ret = dev_p->storage_error;
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)
2070 cy_as_device *dev_p = (cy_as_device *)handle;
2072 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2073 return CY_AS_ERROR_INVALID_HANDLE;
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);
2079 EXPORT_SYMBOL(cy_as_storage_read);
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)
2087 cy_as_device *dev_p = (cy_as_device *)handle;
2089 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2090 return CY_AS_ERROR_INVALID_HANDLE;
2092 if (dev_p->mtp_turbo_active)
2093 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
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);
2100 EXPORT_SYMBOL(cy_as_storage_write);
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)
2108 cy_as_device *dev_p = (cy_as_device *)handle;
2110 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2111 return CY_AS_ERROR_INVALID_HANDLE;
2114 return CY_AS_ERROR_NULL_CALLBACK;
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);
2121 EXPORT_SYMBOL(cy_as_storage_read_async);
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)
2129 cy_as_device *dev_p = (cy_as_device *)handle;
2131 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2132 return CY_AS_ERROR_INVALID_HANDLE;
2135 return CY_AS_ERROR_NULL_CALLBACK;
2137 if (dev_p->mtp_turbo_active)
2138 return CY_AS_ERROR_NOT_VALID_DURING_MTP;
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);
2145 EXPORT_SYMBOL(cy_as_storage_write_async);
2148 my_storage_cancel_callback(
2149 cy_as_device *dev_p,
2151 cy_as_ll_request_response *rqt,
2152 cy_as_ll_request_response *resp,
2153 cy_as_return_status_t stat)
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);
2165 cy_as_return_status_t
2166 cy_as_storage_cancel_async(cy_as_device_handle handle)
2168 cy_as_return_status_t ret;
2169 cy_as_ll_request_response *req_p , *reply_p;
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;
2175 ret = is_storage_active(dev_p);
2176 if (ret != CY_AS_ERROR_SUCCESS)
2179 if (!cy_as_device_is_storage_async_pending(dev_p))
2180 return CY_AS_ERROR_ASYNC_NOT_PENDING;
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.
2188 req_p = cy_as_ll_create_request(dev_p, CY_RQT_ABORT_P2S_XFER,
2189 CY_RQT_GENERAL_RQT_CONTEXT, 1);
2191 return CY_AS_ERROR_OUT_OF_MEMORY;
2193 reply_p = cy_as_ll_create_response(dev_p, 1);
2195 cy_as_ll_destroy_request(dev_p, req_p);
2196 return CY_AS_ERROR_OUT_OF_MEMORY;
2199 ret = cy_as_ll_send_request(dev_p, req_p,
2200 reply_p, cy_false, my_storage_cancel_callback);
2202 cy_as_ll_destroy_request(dev_p, req_p);
2203 cy_as_ll_destroy_response(dev_p, reply_p);
2206 return CY_AS_ERROR_SUCCESS;
2208 EXPORT_SYMBOL(cy_as_storage_cancel_async);
2211 * This function does all the API side clean-up associated with
2212 * CyAsStorageStop, without any communication with the firmware.
2214 void cy_as_storage_cleanup(cy_as_device *dev_p)
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));
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;
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)
2238 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2239 uint8_t resp_type, i;
2241 uint8_t length = info->length;
2242 uint8_t *data_p = info->buf_p;
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;
2249 resp_len = cy_as_ll_request_response__get_word(reply_p, 0);
2250 cy_as_hal_assert(resp_len >= length);
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.
2259 temp = ((resp_p[i] << 6) | (resp_p[i + 1] >> 10));
2262 *data_p++ = (uint8_t)(temp >> 8);
2266 *data_p++ = (uint8_t)(temp & 0xFF);
2271 if (resp_type == CY_RESP_SUCCESS_FAILURE)
2272 ret = cy_as_ll_request_response__get_word(reply_p, 0);
2274 ret = CY_AS_ERROR_INVALID_RESPONSE;
2277 cy_as_ll_destroy_response(dev_p, reply_p);
2278 cy_as_ll_destroy_request(dev_p, req_p);
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,
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,
2293 cy_as_ll_request_response *req_p , *reply_p;
2294 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2298 * sanity checks required before sending the request to the
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;
2305 ret = is_storage_active(dev_p);
2306 if (ret != CY_AS_ERROR_SUCCESS)
2309 if (device >= CY_AS_MAX_STORAGE_DEVICES)
2310 return CY_AS_ERROR_NO_SUCH_DEVICE;
2312 if (reg_type > cy_as_sd_reg_CSD)
2313 return CY_AS_ERROR_INVALID_PARAMETER;
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;
2321 * find the amount of data to be returned. this will be the minimum of
2322 * the actual data length, and the length requested.
2325 case cy_as_sd_reg_OCR:
2326 length = CY_AS_SD_REG_OCR_LENGTH;
2328 case cy_as_sd_reg_CID:
2329 length = CY_AS_SD_REG_CID_LENGTH;
2331 case cy_as_sd_reg_CSD:
2332 length = CY_AS_SD_REG_CSD_LENGTH;
2337 cy_as_hal_assert(0);
2340 if (length < data_p->length)
2341 data_p->length = length;
2342 length = data_p->length;
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);
2348 return CY_AS_ERROR_OUT_OF_MEMORY;
2350 cy_as_ll_request_response__set_word(req_p, 0,
2351 (create_address(bus, device, 0) | (uint16_t)reg_type));
2353 reply_p = cy_as_ll_create_response(dev_p,
2354 CY_AS_SD_REG_MAX_RESP_LENGTH);
2356 cy_as_ll_destroy_request(dev_p, req_p);
2357 return CY_AS_ERROR_OUT_OF_MEMORY;
2361 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2362 if (ret != CY_AS_ERROR_SUCCESS)
2365 return my_handle_response_sd_reg_read(dev_p,
2366 req_p, reply_p, data_p);
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);
2373 if (ret != CY_AS_ERROR_SUCCESS)
2376 /* The request and response are freed as part of the
2377 * MiscFuncCallback */
2382 cy_as_ll_destroy_request(dev_p, req_p);
2383 cy_as_ll_destroy_response(dev_p, reply_p);
2387 EXPORT_SYMBOL(cy_as_storage_sd_register_read);
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,
2395 /* of P-port only partition in blocks */
2397 cy_as_function_callback cb,
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;
2404 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2405 return CY_AS_ERROR_INVALID_HANDLE;
2407 ret = is_storage_active(dev_p);
2408 if (ret != CY_AS_ERROR_SUCCESS)
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;
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);
2421 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
2427 cy_as_ll_destroy_request(dev_p, req_p);
2428 return CY_AS_ERROR_OUT_OF_MEMORY;
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));
2438 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2439 if (ret != CY_AS_ERROR_SUCCESS)
2442 return my_handle_response_no_data(dev_p, req_p, reply_p);
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);
2449 if (ret != CY_AS_ERROR_SUCCESS)
2452 /* The request and response are freed as part of the
2459 cy_as_ll_destroy_request(dev_p, req_p);
2460 cy_as_ll_destroy_response(dev_p, reply_p);
2464 EXPORT_SYMBOL(cy_as_storage_create_p_partition);
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,
2471 cy_as_function_callback cb,
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;
2478 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2479 return CY_AS_ERROR_INVALID_HANDLE;
2481 ret = is_storage_active(dev_p);
2482 if (ret != CY_AS_ERROR_SUCCESS)
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;
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);
2494 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
2500 cy_as_ll_destroy_request(dev_p, req_p);
2501 return CY_AS_ERROR_OUT_OF_MEMORY;
2504 cy_as_ll_request_response__set_word(req_p,
2505 0, create_address(bus, (uint8_t)device, 0x00));
2508 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2509 if (ret != CY_AS_ERROR_SUCCESS)
2512 return my_handle_response_no_data(dev_p, req_p, reply_p);
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);
2519 if (ret != CY_AS_ERROR_SUCCESS)
2522 /* The request and response are freed
2523 * as part of the FuncCallback */
2529 cy_as_ll_destroy_request(dev_p, req_p);
2530 cy_as_ll_destroy_response(dev_p, reply_p);
2534 EXPORT_SYMBOL(cy_as_storage_remove_p_partition);
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)
2542 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2543 uint8_t code = cy_as_ll_request_response__get_code(reply_p);
2546 if (code != CY_RESP_TRANSFER_COUNT) {
2547 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
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);
2560 cy_as_ll_destroy_request(dev_p, req_p);
2561 cy_as_ll_destroy_response(dev_p, reply_p);
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,
2571 cy_as_m_s_c_progress_data *data_p,
2572 cy_as_function_callback cb,
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;
2580 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2581 return CY_AS_ERROR_INVALID_HANDLE;
2583 ret = is_storage_active(dev_p);
2584 if (ret != CY_AS_ERROR_SUCCESS)
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;
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);
2596 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
2602 cy_as_ll_destroy_request(dev_p, req_p);
2603 return CY_AS_ERROR_OUT_OF_MEMORY;
2606 cy_as_ll_request_response__set_word(req_p, 0,
2607 create_address(bus, (uint8_t)device, 0x00));
2610 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2611 if (ret != CY_AS_ERROR_SUCCESS)
2614 return my_handle_response_get_transfer_amount(dev_p,
2615 req_p, reply_p, data_p);
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);
2622 if (ret != CY_AS_ERROR_SUCCESS)
2625 /* The request and response are freed as part of the
2631 cy_as_ll_destroy_request(dev_p, req_p);
2632 cy_as_ll_destroy_response(dev_p, reply_p);
2637 EXPORT_SYMBOL(cy_as_storage_get_transfer_amount);
2639 cy_as_return_status_t
2640 cy_as_storage_erase(
2641 cy_as_device_handle handle,
2642 cy_as_bus_number_t bus,
2644 uint32_t erase_unit,
2645 uint16_t num_erase_units,
2646 cy_as_function_callback cb,
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;
2654 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2655 return CY_AS_ERROR_INVALID_HANDLE;
2657 ret = is_storage_active(dev_p);
2658 if (ret != CY_AS_ERROR_SUCCESS)
2661 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
2662 return CY_AS_ERROR_NO_SUCH_BUS;
2664 if (device >= CY_AS_MAX_STORAGE_DEVICES)
2665 return CY_AS_ERROR_NO_SUCH_DEVICE;
2667 if (dev_p->storage_device_info[bus][device].block_size == 0)
2668 return CY_AS_ERROR_QUERY_DEVICE_NEEDED;
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;
2675 if (num_erase_units == 0)
2676 return CY_AS_ERROR_SUCCESS;
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);
2683 return CY_AS_ERROR_OUT_OF_MEMORY;
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);
2689 cy_as_ll_destroy_request(dev_p, req_p);
2690 return CY_AS_ERROR_OUT_OF_MEMORY;
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));
2705 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
2706 if (ret != CY_AS_ERROR_SUCCESS)
2709 ret = my_handle_response_no_data(dev_p, req_p, reply_p);
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;
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);
2725 if (ret != CY_AS_ERROR_SUCCESS)
2728 /* The request and response are freed
2729 * as part of the FuncCallback */
2734 cy_as_ll_destroy_request(dev_p, req_p);
2735 cy_as_ll_destroy_response(dev_p, reply_p);
2739 EXPORT_SYMBOL(cy_as_storage_erase);
2742 cy_as_storage_func_callback(cy_as_device *dev_p,
2744 cy_as_ll_request_response *rqt,
2745 cy_as_ll_request_response *resp,
2746 cy_as_return_status_t stat)
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;
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;
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);
2767 cntxt = cy_as_ll_request_response__get_context(rqt);
2768 cy_as_hal_assert(cntxt == CY_RQT_STORAGE_RQT_CONTEXT);
2770 code = cy_as_ll_request_response__get_code(rqt);
2772 case CY_RQT_START_STORAGE:
2773 ret = my_handle_response_storage_start(dev_p, rqt, resp, stat);
2775 case CY_RQT_STOP_STORAGE:
2776 ret = my_handle_response_storage_stop(dev_p, rqt, resp, stat);
2778 case CY_RQT_CLAIM_STORAGE:
2779 ret = my_handle_response_storage_claim(dev_p, rqt, resp);
2781 case CY_RQT_RELEASE_STORAGE:
2782 ret = my_handle_response_storage_release(dev_p, rqt, resp);
2784 case CY_RQT_QUERY_MEDIA:
2785 cy_as_hal_assert(cy_false);/* Not used any more. */
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);
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);
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);
2802 case CY_RQT_SD_INTERFACE_CONTROL:
2803 ret = my_handle_response_no_data(dev_p, rqt, resp);
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);
2810 case CY_RQT_PARTITION_STORAGE:
2811 ret = my_handle_response_no_data(dev_p, rqt, resp);
2813 case CY_RQT_PARTITION_ERASE:
2814 ret = my_handle_response_no_data(dev_p, rqt, resp);
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);
2822 ret = my_handle_response_no_data(dev_p, rqt, resp);
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;
2834 ret = CY_AS_ERROR_INVALID_RESPONSE;
2835 cy_as_hal_assert(cy_false);
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.
2844 if (stat == CY_AS_ERROR_SUCCESS)
2847 /* Call the user callback, if there is one */
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);
2856 cy_as_sdio_sync_reply_callback(
2857 cy_as_device *dev_p,
2859 cy_as_ll_request_response *rqt,
2860 cy_as_ll_request_response *resp,
2861 cy_as_return_status_t ret)
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);
2876 cy_as_dma_cancel(dev_p,
2877 dev_p->storage_write_endpoint, ret);
2880 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
2889 dev_p->storage_error = (ret & 0x00FF) ?
2890 CY_AS_ERROR_INVALID_RESPONSE : CY_AS_ERROR_SUCCESS;
2892 /* Wake any threads/processes that are waiting on
2893 * the read/write completion. */
2894 cy_as_hal_wake(&dev_p->context[context]->channel);
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,
2903 if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE))
2904 return CY_AS_ERROR_INVALID_HANDLE;
2906 if (bus < 0 || bus >= CY_AS_MAX_BUSES)
2907 return CY_AS_ERROR_NO_SUCH_BUS;
2909 if (device >= CY_AS_MAX_STORAGE_DEVICES)
2910 return CY_AS_ERROR_NO_SUCH_DEVICE;
2912 if (!cy_as_device_is_astoria_dev(dev_p))
2913 return CY_AS_ERROR_NOT_SUPPORTED;
2915 return (is_storage_active(dev_p));
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,
2923 uint8_t n_function_no,
2930 cy_as_ll_request_response *req_p , *reply_p;
2931 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
2935 * sanity checks required before sending the request to the
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)
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;
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);
2954 return CY_AS_ERROR_OUT_OF_MEMORY;
2956 /*Setting up request*/
2958 cy_as_ll_request_response__set_word(req_p, 0,
2959 create_address(bus, (uint8_t)device, n_function_no));
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)));
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));
2973 cy_as_ll_request_response__set_word(req_p, 2,
2974 ((uint16_t)((address&0x00007fff)<<1)));
2977 reply_p = cy_as_ll_create_response(dev_p, 2);
2980 cy_as_ll_destroy_request(dev_p, req_p);
2981 return CY_AS_ERROR_OUT_OF_MEMORY;
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)
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);
2994 ret = CY_AS_ERROR_INVALID_RESPONSE;
2995 else if (data_p != 0)
2996 *(uint8_t *)(data_p) = (uint8_t)(resp_data&0x00ff);
2998 ret = CY_AS_ERROR_INVALID_RESPONSE;
3003 cy_as_ll_destroy_request(dev_p, req_p);
3005 cy_as_ll_destroy_response(dev_p, reply_p);
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,
3015 uint8_t n_function_no,
3020 return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
3021 address, misc_buf, 0x00, cy_false, data_p);
3023 EXPORT_SYMBOL(cy_as_sdio_direct_read);
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,
3030 uint8_t n_function_no,
3036 return cy_as_sdio_direct_io(handle, bus, device, n_function_no,
3037 address, misc_buf, argument, cy_true, data_p);
3039 EXPORT_SYMBOL(cy_as_sdio_direct_write);
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,
3047 uint8_t n_function_no,
3055 cy_as_ll_request_response *req_p , *reply_p;
3056 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3060 cy_as_context *ctxt_p;
3061 uint32_t dmasize, loopcount = 200;
3062 cy_as_end_point_number_t ep;
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)
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;
3076 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3077 (dev_p->storage_wait))
3078 return CY_AS_ERROR_ASYNC_PENDING;
3080 /* Request for 0 bytes of blocks is returned as a success*/
3082 return CY_AS_ERROR_SUCCESS;
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;
3089 reqtype = CY_RQT_SDIO_READ_EXTENDED;
3090 ep = dev_p->storage_read_endpoint;
3093 req_p = dev_p->storage_rw_req_p;
3094 cy_as_ll_init_request(req_p, reqtype, CY_RQT_STORAGE_RQT_CONTEXT, 3);
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);
3100 /* Setup the DMA request */
3101 if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
3103 dev_p->sdiocard[bus].
3104 function[n_function_no-1].blocksize)
3105 return CY_AS_ERROR_INVALID_BLOCKSIZE;
3109 return CY_AS_ERROR_INVALID_BLOCKSIZE;
3112 if (argument == 512)
3115 dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
3116 dev_p->sdiocard[bus].function[n_function_no-1].blocksize
3117 * argument : argument;
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);
3123 if (ret != CY_AS_ERROR_SUCCESS)
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);
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);
3143 if (ret != CY_AS_ERROR_SUCCESS) {
3144 cy_as_dma_cancel(dev_p, ep, CY_AS_ERROR_CANCELED);
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);
3150 while (loopcount-- > 0) {
3151 if (dev_p->storage_wait == cy_false)
3153 cy_as_hal_sleep_on(&ctxt_p->channel, 10);
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;
3161 ret = dev_p->storage_error;
3163 if (ret != CY_AS_ERROR_SUCCESS)
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;
3172 ret = CY_AS_ERROR_INVALID_REQUEST;
3175 ret = CY_AS_ERROR_INVALID_RESPONSE;
3183 cy_as_sdio_async_reply_callback(
3184 cy_as_device *dev_p,
3186 cy_as_ll_request_response *rqt,
3187 cy_as_ll_request_response *resp,
3188 cy_as_return_status_t ret)
3190 cy_as_storage_callback cb_ms;
3192 uint32_t pendingblocks;
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);
3206 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
3215 cy_as_dma_cancel(dev_p,
3216 dev_p->storage_write_endpoint, ret);
3218 dev_p->storage_error = ret;
3221 dev_p->storage_wait = cy_false;
3224 * if the DMA callback has already been called,
3225 * the user callback has to be called from here.
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;
3231 dev_p->storage_cb = 0;
3232 dev_p->storage_cb_ms = 0;
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
3242 ret = CY_AS_ERROR_INVALID_RESPONSE;
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);
3249 dev_p->storage_error = ret;
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,
3258 uint8_t n_function_no,
3264 cy_as_storage_callback callback)
3269 cy_as_ll_request_response *req_p , *reply_p;
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;
3275 ret = cy_as_sdio_device_check(dev_p, bus, device);
3276 if (ret != CY_AS_ERROR_SUCCESS)
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;
3286 return CY_AS_ERROR_NULL_CALLBACK;
3288 /* We are supposed to return sucess if the number of
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;
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.
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;
3311 cy_as_device_set_storage_async_pending(dev_p);
3312 cy_as_hal_enable_interrupts(mask);
3316 * storage information about the currently
3317 * outstanding request
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;
3325 if (is_write == cy_true) {
3326 reqtype = CY_RQT_SDIO_WRITE_EXTENDED;
3327 ep = dev_p->storage_write_endpoint;
3329 reqtype = CY_RQT_SDIO_READ_EXTENDED;
3330 ep = dev_p->storage_read_endpoint;
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);
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);
3342 if (!(misc_buf&CY_SDIO_BLOCKMODE)) {
3344 dev_p->sdiocard[bus].function[n_function_no-1].blocksize)
3345 return CY_AS_ERROR_INVALID_BLOCKSIZE;
3349 return CY_AS_ERROR_INVALID_BLOCKSIZE;
3352 if (argument == 512)
3354 dmasize = ((misc_buf&CY_SDIO_BLOCKMODE) != 0) ?
3355 dev_p->sdiocard[bus].function[n_function_no-1].blocksize *
3356 argument : argument;
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;
3371 if (ret != CY_AS_ERROR_SUCCESS) {
3372 cy_as_device_clear_storage_async_pending(dev_p);
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);
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);
3395 cy_as_dma_kick_start(dev_p, ep);
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,
3407 uint8_t n_function_no,
3412 cy_as_sdio_callback callback)
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);
3419 return cy_as_sdio_extended_i_o_async(handle, bus, device,
3420 n_function_no, address, misc_buf, argument, cy_false,
3423 EXPORT_SYMBOL(cy_as_sdio_extended_read);
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,
3431 uint8_t n_function_no,
3436 cy_as_sdio_callback callback)
3439 return cy_as_sdio_extended_i_o(handle, bus, device,
3440 n_function_no, address, misc_buf, argument, cy_true,
3443 return cy_as_sdio_extended_i_o_async(handle, bus, device,
3444 n_function_no, address, misc_buf, argument, cy_true,
3447 EXPORT_SYMBOL(cy_as_sdio_extended_write);
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,
3455 uint8_t n_function_no,
3460 cy_as_ll_request_response *req_p , *reply_p;
3461 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3463 cy_as_context *ctxt_p;
3464 uint32_t loopcount = 200;
3466 cy_as_device *dev_p = (cy_as_device *)handle;
3468 ret = cy_as_sdio_device_check(dev_p, bus, device);
3469 if (ret != CY_AS_ERROR_SUCCESS)
3472 if (!(cy_as_sdio_check_function_initialized(handle, bus, 0)))
3473 return CY_AS_ERROR_INVALID_FUNCTION;
3475 if ((cy_as_device_is_storage_async_pending(dev_p)) ||
3476 (dev_p->storage_wait))
3477 return CY_AS_ERROR_ASYNC_PENDING;
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);
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);
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);
3493 if (ret != CY_AS_ERROR_SUCCESS)
3496 cy_as_ll_request_response__set_word(req_p, 0,
3497 create_address(bus, (uint8_t)device, n_function_no));
3499 /* Set tuple id to fetch. */
3500 cy_as_ll_request_response__set_word(req_p, 1, tuple_id<<8);
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);
3507 if (ret != CY_AS_ERROR_SUCCESS) {
3508 cy_as_dma_cancel(dev_p,
3509 dev_p->storage_read_endpoint, CY_AS_ERROR_CANCELED);
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);
3516 while (loopcount-- > 0) {
3517 if (dev_p->storage_wait == cy_false)
3519 cy_as_hal_sleep_on(&ctxt_p->channel, 10);
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;
3527 ret = dev_p->storage_error;
3529 if (ret != CY_AS_ERROR_SUCCESS)
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
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);
3543 ret = CY_AS_ERROR_INVALID_RESPONSE;
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,
3555 cy_as_sdio_card *data_p)
3557 cy_as_ll_request_response *req_p , *reply_p;
3558 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3561 cy_as_device *dev_p = (cy_as_device *)handle;
3563 ret = cy_as_sdio_device_check(dev_p, bus, device);
3564 if (ret != CY_AS_ERROR_SUCCESS)
3567 /* Allocating memory to the SDIO device structure in dev_p */
3569 cy_as_hal_mem_set(&dev_p->sdiocard[bus], 0, sizeof(cy_as_sdio_device));
3571 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_QUERY_CARD,
3572 CY_RQT_STORAGE_RQT_CONTEXT, 1);
3574 return CY_AS_ERROR_OUT_OF_MEMORY;
3576 cy_as_ll_request_response__set_word(req_p, 0,
3577 create_address(bus, (uint8_t)device, 0));
3579 reply_p = cy_as_ll_create_response(dev_p, 5);
3581 cy_as_ll_destroy_request(dev_p, req_p);
3582 return CY_AS_ERROR_OUT_OF_MEMORY;
3585 ret = cy_as_ll_send_request_wait_reply(dev_p,
3588 if (ret != CY_AS_ERROR_SUCCESS)
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 =
3599 dev_p->sdiocard[bus].card.manufacturer_info =
3601 dev_p->sdiocard[bus].card.blocksize =
3603 dev_p->sdiocard[bus].card.maxblocksize =
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;
3626 if (resp_type == CY_RESP_SUCCESS_FAILURE)
3627 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3629 ret = CY_AS_ERROR_INVALID_RESPONSE;
3633 cy_as_ll_destroy_request(dev_p, req_p);
3635 cy_as_ll_destroy_response(dev_p, reply_p);
3638 EXPORT_SYMBOL(cy_as_sdio_query_card);
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,
3648 cy_as_ll_request_response *req_p , *reply_p;
3649 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3651 cy_as_device *dev_p = (cy_as_device *)handle;
3653 ret = cy_as_sdio_device_check(dev_p, bus, device);
3655 if (ret != CY_AS_ERROR_SUCCESS)
3658 if (dev_p->sdiocard != 0) {
3659 dev_p->sdiocard[bus].function_init_map = 0;
3660 dev_p->sdiocard[bus].function_suspended_map = 0;
3663 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_RESET_DEV,
3664 CY_RQT_STORAGE_RQT_CONTEXT, 1);
3667 return CY_AS_ERROR_OUT_OF_MEMORY;
3670 cy_as_ll_request_response__set_word(req_p, 0,
3671 create_address(bus, (uint8_t)device, 0));
3673 reply_p = cy_as_ll_create_response(dev_p, 2);
3675 cy_as_ll_destroy_request(dev_p, req_p);
3676 return CY_AS_ERROR_OUT_OF_MEMORY;
3679 ret = cy_as_ll_send_request_wait_reply(dev_p,
3682 if (ret != CY_AS_ERROR_SUCCESS)
3685 resp_type = cy_as_ll_request_response__get_code(reply_p);
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);
3692 ret = CY_AS_ERROR_INVALID_RESPONSE;
3696 cy_as_ll_destroy_request(dev_p, req_p);
3698 cy_as_ll_destroy_response(dev_p, reply_p);
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,
3708 uint8_t n_function_no,
3711 cy_as_ll_request_response *req_p , *reply_p;
3712 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3714 cy_as_device *dev_p = (cy_as_device *)handle;
3716 ret = cy_as_sdio_device_check(dev_p, bus, device);
3718 if (ret != CY_AS_ERROR_SUCCESS)
3721 if (!(cy_as_sdio_check_function_initialized
3723 return CY_AS_ERROR_NOT_RUNNING;
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));
3731 return CY_AS_ERROR_ALREADY_RUNNING;
3734 req_p = cy_as_ll_create_request(dev_p,
3735 CY_RQT_SDIO_INIT_FUNCTION, CY_RQT_STORAGE_RQT_CONTEXT, 1);
3737 return CY_AS_ERROR_OUT_OF_MEMORY;
3739 cy_as_ll_request_response__set_word(req_p, 0,
3740 create_address(bus, (uint8_t)device, n_function_no));
3742 reply_p = cy_as_ll_create_response(dev_p, 5);
3744 cy_as_ll_destroy_request(dev_p, req_p);
3745 return CY_AS_ERROR_OUT_OF_MEMORY;
3748 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3750 if (ret != CY_AS_ERROR_SUCCESS)
3753 resp_type = cy_as_ll_request_response__get_code(reply_p);
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 =
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);
3776 if (resp_type == CY_RESP_SUCCESS_FAILURE)
3777 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3779 ret = CY_AS_ERROR_INVALID_FUNCTION;
3784 cy_as_ll_destroy_request(dev_p, req_p);
3786 cy_as_ll_destroy_response(dev_p, reply_p);
3789 EXPORT_SYMBOL(cy_as_sdio_init_function);
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,
3797 uint8_t n_function_no,
3798 cy_as_sdio_func *data_p)
3800 cy_as_device *dev_p = (cy_as_device *)handle;
3801 cy_as_return_status_t ret;
3803 ret = cy_as_sdio_device_check(dev_p, bus, device);
3804 if (ret != CY_AS_ERROR_SUCCESS)
3807 if (!(cy_as_sdio_check_function_initialized(handle,
3808 bus, n_function_no)))
3809 return CY_AS_ERROR_INVALID_FUNCTION;
3812 dev_p->sdiocard[bus].function[n_function_no-1].blocksize;
3814 dev_p->sdiocard[bus].function[n_function_no-1].card_psn;
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].
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;
3827 return CY_AS_ERROR_SUCCESS;
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,
3836 uint8_t n_function_no)
3838 cy_as_ll_request_response *req_p , *reply_p;
3839 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
3841 cy_as_device *dev_p = (cy_as_device *)handle;
3843 ret = cy_as_sdio_device_check(dev_p, bus, device);
3844 if (ret != CY_AS_ERROR_SUCCESS)
3847 if (!(cy_as_sdio_check_function_initialized(handle,
3848 bus, n_function_no)))
3849 return CY_AS_ERROR_INVALID_FUNCTION;
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) &
3855 return CY_AS_ERROR_INVALID_COMMAND;
3858 req_p = cy_as_ll_create_request(dev_p, CY_RQT_SDIO_ABORT_IO,
3859 CY_RQT_GENERAL_RQT_CONTEXT, 1);
3862 return CY_AS_ERROR_OUT_OF_MEMORY;
3865 cy_as_ll_request_response__set_word(req_p, 0,
3866 create_address(bus, (uint8_t)device, n_function_no));
3868 reply_p = cy_as_ll_create_response(dev_p, 2);
3870 cy_as_ll_destroy_request(dev_p, req_p);
3871 return CY_AS_ERROR_OUT_OF_MEMORY;
3874 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3875 if (ret != CY_AS_ERROR_SUCCESS)
3878 resp_type = cy_as_ll_request_response__get_code(reply_p);
3880 if (resp_type == CY_RESP_SUCCESS_FAILURE)
3881 ret = cy_as_ll_request_response__get_word(reply_p, 0);
3883 ret = CY_AS_ERROR_INVALID_RESPONSE;
3888 cy_as_ll_destroy_request(dev_p, req_p);
3890 cy_as_ll_destroy_response(dev_p, reply_p);
3894 /* Suspend IO to current function*/
3895 cy_as_return_status_t
3897 cy_as_device_handle handle,
3898 cy_as_bus_number_t bus,
3900 uint8_t n_function_no)
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;
3906 ret = cy_as_sdio_device_check(dev_p, bus, device);
3907 if (ret != CY_AS_ERROR_SUCCESS)
3910 if (!(cy_as_sdio_check_function_initialized(handle, bus,
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;
3920 req_p = cy_as_ll_create_request(dev_p,
3921 CY_RQT_SDIO_SUSPEND, CY_RQT_GENERAL_RQT_CONTEXT, 1);
3923 return CY_AS_ERROR_OUT_OF_MEMORY;
3926 cy_as_ll_request_response__set_word(req_p, 0,
3927 create_address(bus, (uint8_t)device, n_function_no));
3929 reply_p = cy_as_ll_create_response(dev_p, 2);
3931 cy_as_ll_destroy_request(dev_p, req_p);
3932 return CY_AS_ERROR_OUT_OF_MEMORY;
3934 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
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);
3942 cy_as_ll_destroy_request(dev_p, req_p);
3944 cy_as_ll_destroy_response(dev_p, reply_p);
3949 /*Resume suspended function*/
3950 cy_as_return_status_t
3952 cy_as_device_handle handle,
3953 cy_as_bus_number_t bus,
3955 uint8_t n_function_no,
3958 uint16_t pendingblockcount,
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;
3966 ret = cy_as_sdio_device_check(dev_p, bus, device);
3967 if (ret != CY_AS_ERROR_SUCCESS)
3970 if (!(cy_as_sdio_check_function_initialized
3971 (handle, bus, n_function_no)))
3972 return CY_AS_ERROR_INVALID_FUNCTION;
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;
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;
3983 req_p = cy_as_ll_create_request(dev_p,
3984 CY_RQT_SDIO_RESUME, CY_RQT_STORAGE_RQT_CONTEXT, 1);
3986 return CY_AS_ERROR_OUT_OF_MEMORY;
3989 cy_as_ll_request_response__set_word(req_p, 0,
3990 create_address(bus, (uint8_t)device, n_function_no));
3992 reply_p = cy_as_ll_create_response(dev_p, 2);
3994 cy_as_ll_destroy_request(dev_p, req_p);
3995 return CY_AS_ERROR_OUT_OF_MEMORY;
3997 ret = cy_as_ll_send_request_wait_reply(dev_p, req_p, reply_p);
3999 if (ret != CY_AS_ERROR_SUCCESS)
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);
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);
4017 ret = CY_AS_ERROR_SUCCESS;
4020 ret = CY_AS_ERROR_INVALID_RESPONSE;
4024 cy_as_sdio_clear_function_suspended(handle, bus, n_function_no);
4026 cy_as_ll_destroy_request(dev_p, req_p);
4028 cy_as_ll_destroy_response(dev_p, reply_p);
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,
4040 uint8_t n_function_no,
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)
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
4057 return CY_AS_ERROR_SUCCESS;
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;
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)
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);
4079 if (ret != CY_AS_ERROR_SUCCESS)
4082 if (n_function_no == 0)
4083 cy_as_sdio_set_card_block_size(handle, bus, blocksize);
4085 cy_as_sdio_set_function_block_size(handle,
4086 bus, n_function_no, blocksize);
4089 EXPORT_SYMBOL(cy_as_sdio_set_blocksize);
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,
4097 uint8_t n_function_no)
4099 cy_as_return_status_t ret;
4102 if (n_function_no == 0)
4103 return CY_AS_ERROR_INVALID_FUNCTION;
4105 ret = cy_as_sdio_device_check((cy_as_device *)handle, bus, device);
4106 if (ret != CY_AS_ERROR_SUCCESS)
4109 if (!(cy_as_sdio_check_function_initialized
4110 (handle, bus, n_function_no)))
4111 return CY_AS_ERROR_SUCCESS;
4113 temp = (uint8_t)(((cy_as_device *)handle)->sdiocard[bus].
4114 function_init_map & (~(1 << n_function_no)));
4116 cy_as_sdio_direct_write(handle, bus, device, 0, 0x02, 0, temp, 0);
4118 ((cy_as_device *)handle)->sdiocard[bus].function_init_map &=
4119 (~(1 << n_function_no));
4121 return CY_AS_ERROR_SUCCESS;