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