]>
Commit | Line | Data |
---|---|---|
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 */ | |
42 | cy_as_return_status_t | |
43 | cy_an_map_bus_from_media_type(cy_as_device *dev_p, | |
44 | cy_as_media_type type, cy_as_bus_number_t *bus) | |
45 | { | |
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 | ||
77 | static uint16_t | |
78 | create_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 | ||
86 | cy_as_media_type | |
87 | cy_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 | ||
117 | cy_as_bus_number_t | |
118 | cy_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 | ||
125 | uint32_t | |
126 | cy_as_storage_get_device_from_address(uint16_t v) | |
127 | { | |
0769c38d | 128 | return (uint32_t)((v >> 8) & 0x0f); |
81eb669b DC |
129 | } |
130 | ||
131 | static uint8_t | |
132 | get_unit_from_address(uint16_t v) | |
133 | { | |
0769c38d | 134 | return (uint8_t)(v & 0xff); |
81eb669b DC |
135 | } |
136 | ||
137 | static cy_as_return_status_t | |
138 | cy_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 | ||
160 | static void | |
161 | my_storage_request_callback(cy_as_device *dev_p, | |
162 | uint8_t context, | |
163 | cy_as_ll_request_response *req_p, | |
164 | cy_as_ll_request_response *resp_p, | |
165 | cy_as_return_status_t ret) | |
166 | { | |
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 | ||
321 | static cy_as_return_status_t | |
322 | is_storage_active(cy_as_device *dev_p) | |
323 | { | |
324 | if (!cy_as_device_is_configured(dev_p)) | |
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 | ||
339 | static void | |
340 | cy_as_storage_func_callback(cy_as_device *dev_p, | |
341 | uint8_t context, | |
342 | cy_as_ll_request_response *rqt, | |
343 | cy_as_ll_request_response *resp, | |
0769c38d | 344 | cy_as_return_status_t ret); |
81eb669b DC |
345 | |
346 | static cy_as_return_status_t | |
347 | my_handle_response_no_data(cy_as_device *dev_p, | |
348 | cy_as_ll_request_response *req_p, | |
349 | cy_as_ll_request_response *reply_p) | |
350 | { | |
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 | |
361 | destroy: | |
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 | ||
368 | static cy_as_return_status_t | |
369 | my_handle_response_storage_start(cy_as_device *dev_p, | |
370 | cy_as_ll_request_response *req_p, | |
371 | cy_as_ll_request_response *reply_p, | |
372 | cy_as_return_status_t ret) | |
373 | { | |
374 | if (ret != CY_AS_ERROR_SUCCESS) | |
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 | ||
425 | destroy: | |
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 | ||
446 | cy_as_return_status_t | |
447 | cy_as_storage_start(cy_as_device_handle handle, | |
448 | cy_as_function_callback cb, | |
449 | uint32_t client) | |
450 | { | |
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 | ||
512 | destroy: | |
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 | 525 | EXPORT_SYMBOL(cy_as_storage_start); |
81eb669b DC |
526 | |
527 | static cy_as_return_status_t | |
528 | my_handle_response_storage_stop(cy_as_device *dev_p, | |
529 | cy_as_ll_request_response *req_p, | |
530 | cy_as_ll_request_response *reply_p, | |
531 | cy_as_return_status_t ret) | |
532 | { | |
533 | if (ret != CY_AS_ERROR_SUCCESS) | |
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 | ||
542 | destroy: | |
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 | } |
556 | cy_as_return_status_t | |
557 | cy_as_storage_stop(cy_as_device_handle handle, | |
558 | cy_as_function_callback cb, | |
559 | uint32_t client) | |
560 | { | |
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 | ||
622 | destroy: | |
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 | 635 | EXPORT_SYMBOL(cy_as_storage_stop); |
81eb669b DC |
636 | |
637 | cy_as_return_status_t | |
638 | cy_as_storage_register_callback(cy_as_device_handle handle, | |
639 | cy_as_storage_event_callback callback) | |
640 | { | |
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 | 659 | EXPORT_SYMBOL(cy_as_storage_register_callback); |
81eb669b DC |
660 | |
661 | ||
662 | static cy_as_return_status_t | |
663 | my_handle_response_storage_claim(cy_as_device *dev_p, | |
664 | cy_as_ll_request_response *req_p, | |
665 | cy_as_ll_request_response *reply_p) | |
666 | { | |
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 | |
699 | destroy: | |
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 | ||
706 | static cy_as_return_status_t | |
707 | my_storage_claim(cy_as_device *dev_p, | |
708 | void *data, | |
709 | cy_as_bus_number_t bus, | |
710 | uint32_t device, | |
711 | uint16_t req_flags, | |
712 | cy_as_function_callback cb, | |
713 | uint32_t client) | |
714 | { | |
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 | ||
765 | destroy: | |
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 | ||
772 | cy_as_return_status_t | |
773 | cy_as_storage_claim(cy_as_device_handle handle, | |
774 | cy_as_bus_number_t bus, | |
775 | uint32_t device, | |
776 | cy_as_function_callback cb, | |
777 | uint32_t client) | |
778 | { | |
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 | 787 | EXPORT_SYMBOL(cy_as_storage_claim); |
81eb669b DC |
788 | |
789 | static cy_as_return_status_t | |
790 | my_handle_response_storage_release(cy_as_device *dev_p, | |
791 | cy_as_ll_request_response *req_p, | |
792 | cy_as_ll_request_response *reply_p) | |
793 | { | |
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 | |
827 | destroy: | |
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 | ||
834 | static cy_as_return_status_t | |
835 | my_storage_release(cy_as_device *dev_p, | |
836 | void *data, | |
837 | cy_as_bus_number_t bus, | |
838 | uint32_t device, | |
839 | uint16_t req_flags, | |
840 | cy_as_function_callback cb, | |
841 | uint32_t client) | |
842 | { | |
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 | ||
894 | destroy: | |
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 | ||
901 | cy_as_return_status_t | |
902 | cy_as_storage_release(cy_as_device_handle handle, | |
903 | cy_as_bus_number_t bus, | |
904 | uint32_t device, | |
905 | cy_as_function_callback cb, | |
906 | uint32_t client) | |
907 | { | |
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 | 916 | EXPORT_SYMBOL(cy_as_storage_release); |
81eb669b DC |
917 | |
918 | static cy_as_return_status_t | |
919 | my_handle_response_storage_query_bus(cy_as_device *dev_p, | |
920 | cy_as_ll_request_response *req_p, | |
921 | cy_as_ll_request_response *reply_p, | |
922 | uint32_t *count) | |
923 | { | |
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 | ||
976 | destroy: | |
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 | ||
983 | cy_as_return_status_t | |
984 | my_storage_query_bus(cy_as_device *dev_p, | |
985 | cy_as_bus_number_t bus, | |
986 | cy_as_media_type type, | |
987 | uint16_t req_flags, | |
988 | uint32_t *count, | |
989 | cy_as_function_callback cb, | |
990 | uint32_t client) | |
991 | { | |
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 | ||
1046 | destroy: | |
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 | ||
1053 | cy_as_return_status_t | |
1054 | cy_as_storage_query_bus(cy_as_device_handle handle, | |
1055 | cy_as_bus_number_t bus, | |
1056 | uint32_t *count, | |
1057 | cy_as_function_callback cb, | |
1058 | uint32_t client) | |
1059 | { | |
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 | 1065 | EXPORT_SYMBOL(cy_as_storage_query_bus); |
81eb669b DC |
1066 | |
1067 | cy_as_return_status_t | |
1068 | cy_as_storage_query_media(cy_as_device_handle handle, | |
1069 | cy_as_media_type type, | |
1070 | uint32_t *count, | |
1071 | cy_as_function_callback cb, | |
1072 | uint32_t client) | |
1073 | { | |
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 | 1093 | EXPORT_SYMBOL(cy_as_storage_query_media); |
81eb669b DC |
1094 | |
1095 | static cy_as_return_status_t | |
1096 | my_handle_response_storage_query_device(cy_as_device *dev_p, | |
1097 | cy_as_ll_request_response *req_p, | |
1098 | cy_as_ll_request_response *reply_p, | |
1099 | void *data_p) | |
1100 | { | |
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 | ||
1184 | destroy: | |
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 | ||
1191 | static cy_as_return_status_t | |
1192 | my_storage_query_device(cy_as_device *dev_p, | |
1193 | void *data_p, | |
1194 | uint16_t req_flags, | |
1195 | cy_as_bus_number_t bus, | |
1196 | uint32_t device, | |
1197 | cy_as_function_callback cb, | |
1198 | uint32_t client) | |
1199 | { | |
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 | ||
1250 | destroy: | |
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 | ||
1257 | cy_as_return_status_t | |
1258 | cy_as_storage_query_device(cy_as_device_handle handle, | |
1259 | cy_as_storage_query_device_data *data_p, | |
1260 | cy_as_function_callback cb, | |
1261 | uint32_t client) | |
1262 | { | |
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 | 1268 | EXPORT_SYMBOL(cy_as_storage_query_device); |
81eb669b DC |
1269 | |
1270 | static cy_as_return_status_t | |
1271 | my_handle_response_storage_query_unit(cy_as_device *dev_p, | |
1272 | cy_as_ll_request_response *req_p, | |
1273 | cy_as_ll_request_response *reply_p, | |
1274 | void *data_p) | |
1275 | { | |
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 | |
1353 | destroy: | |
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 | ||
1360 | static cy_as_return_status_t | |
1361 | my_storage_query_unit(cy_as_device *dev_p, | |
1362 | void *data_p, | |
1363 | uint16_t req_flags, | |
1364 | cy_as_bus_number_t bus, | |
1365 | uint32_t device, | |
1366 | uint32_t unit, | |
1367 | cy_as_function_callback cb, | |
1368 | uint32_t client) | |
1369 | { | |
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 | ||
1426 | destroy: | |
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 | ||
1433 | cy_as_return_status_t | |
1434 | cy_as_storage_query_unit(cy_as_device_handle handle, | |
1435 | cy_as_storage_query_unit_data *data_p, | |
1436 | cy_as_function_callback cb, | |
1437 | uint32_t client) | |
1438 | { | |
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 | 1443 | EXPORT_SYMBOL(cy_as_storage_query_unit); |
81eb669b DC |
1444 | |
1445 | static cy_as_return_status_t | |
1446 | cy_as_get_block_size(cy_as_device *dev_p, | |
1447 | cy_as_bus_number_t bus, | |
1448 | uint32_t device, | |
1449 | cy_as_function_callback cb) | |
1450 | { | |
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 | |
1503 | destroy: | |
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 | ||
1510 | cy_as_return_status_t | |
1511 | my_storage_device_control( | |
1512 | cy_as_device *dev_p, | |
1513 | cy_as_bus_number_t bus, | |
1514 | uint32_t device, | |
1515 | cy_bool card_detect_en, | |
1516 | cy_bool write_prot_en, | |
1517 | cy_as_storage_card_detect config_detect, | |
1518 | cy_as_function_callback cb, | |
1519 | uint32_t client) | |
1520 | { | |
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 | } |
1602 | destroy: | |
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 | ||
1609 | cy_as_return_status_t | |
1610 | cy_as_storage_device_control(cy_as_device_handle handle, | |
1611 | cy_as_bus_number_t bus, | |
1612 | uint32_t device, | |
1613 | cy_bool card_detect_en, | |
1614 | cy_bool write_prot_en, | |
1615 | cy_as_storage_card_detect config_detect, | |
1616 | cy_as_function_callback cb, | |
1617 | uint32_t client) | |
1618 | { | |
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 | 1624 | EXPORT_SYMBOL(cy_as_storage_device_control); |
81eb669b DC |
1625 | |
1626 | static void | |
1627 | cy_as_async_storage_callback(cy_as_device *dev_p, | |
1628 | cy_as_end_point_number_t ep, void *buf_p, uint32_t size, | |
1629 | cy_as_return_status_t ret) | |
1630 | { | |
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 | ||
1677 | static void | |
1678 | cy_as_async_storage_reply_callback( | |
1679 | cy_as_device *dev_p, | |
1680 | uint8_t context, | |
1681 | cy_as_ll_request_response *rqt, | |
1682 | cy_as_ll_request_response *resp, | |
1683 | cy_as_return_status_t ret) | |
1684 | { | |
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 | ||
1752 | static cy_as_return_status_t | |
1753 | cy_as_storage_async_oper(cy_as_device *dev_p, cy_as_end_point_number_t ep, | |
1754 | uint8_t reqtype, uint16_t req_flags, cy_as_bus_number_t bus, | |
1755 | uint32_t device, uint32_t unit, uint32_t block, void *data_p, | |
1756 | uint16_t num_blocks, cy_as_storage_callback_dep callback, | |
1757 | cy_as_storage_callback callback_ms) | |
1758 | { | |
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 | ||
1889 | static void | |
1890 | cy_as_sync_storage_callback(cy_as_device *dev_p, | |
1891 | cy_as_end_point_number_t ep, void *buf_p, | |
1892 | uint32_t size, cy_as_return_status_t err) | |
1893 | { | |
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 | ||
1901 | static void | |
1902 | cy_as_sync_storage_reply_callback( | |
1903 | cy_as_device *dev_p, | |
1904 | uint8_t context, | |
1905 | cy_as_ll_request_response *rqt, | |
1906 | cy_as_ll_request_response *resp, | |
1907 | cy_as_return_status_t ret) | |
1908 | { | |
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 | ||
1939 | static cy_as_return_status_t | |
1940 | cy_as_storage_sync_oper(cy_as_device *dev_p, | |
1941 | cy_as_end_point_number_t ep, uint8_t reqtype, | |
1942 | cy_as_bus_number_t bus, uint32_t device, | |
1943 | uint32_t unit, uint32_t block, void *data_p, | |
1944 | uint16_t num_blocks) | |
1945 | { | |
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 | ||
2064 | cy_as_return_status_t | |
2065 | cy_as_storage_read(cy_as_device_handle handle, | |
2066 | cy_as_bus_number_t bus, uint32_t device, | |
2067 | uint32_t unit, uint32_t block, | |
2068 | void *data_p, uint16_t num_blocks) | |
2069 | { | |
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 | 2079 | EXPORT_SYMBOL(cy_as_storage_read); |
81eb669b DC |
2080 | |
2081 | cy_as_return_status_t | |
2082 | cy_as_storage_write(cy_as_device_handle handle, | |
2083 | cy_as_bus_number_t bus, uint32_t device, | |
2084 | uint32_t unit, uint32_t block, void *data_p, | |
2085 | uint16_t num_blocks) | |
2086 | { | |
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 | 2100 | EXPORT_SYMBOL(cy_as_storage_write); |
81eb669b DC |
2101 | |
2102 | cy_as_return_status_t | |
2103 | cy_as_storage_read_async(cy_as_device_handle handle, | |
2104 | cy_as_bus_number_t bus, uint32_t device, uint32_t unit, | |
2105 | uint32_t block, void *data_p, uint16_t num_blocks, | |
2106 | cy_as_storage_callback callback) | |
2107 | { | |
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 | 2121 | EXPORT_SYMBOL(cy_as_storage_read_async); |
81eb669b DC |
2122 | |
2123 | cy_as_return_status_t | |
2124 | cy_as_storage_write_async(cy_as_device_handle handle, | |
2125 | cy_as_bus_number_t bus, uint32_t device, uint32_t unit, | |
2126 | uint32_t block, void *data_p, uint16_t num_blocks, | |
2127 | cy_as_storage_callback callback) | |
2128 | { | |
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 | 2145 | EXPORT_SYMBOL(cy_as_storage_write_async); |
81eb669b DC |
2146 | |
2147 | static void | |
2148 | my_storage_cancel_callback( | |
2149 | cy_as_device *dev_p, | |
2150 | uint8_t context, | |
2151 | cy_as_ll_request_response *rqt, | |
2152 | cy_as_ll_request_response *resp, | |
2153 | cy_as_return_status_t stat) | |
2154 | { | |
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 | ||
2165 | cy_as_return_status_t | |
2166 | cy_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 | 2208 | EXPORT_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 | */ | |
2214 | void 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 | ||
2231 | static cy_as_return_status_t | |
2232 | my_handle_response_sd_reg_read( | |
2233 | cy_as_device *dev_p, | |
2234 | cy_as_ll_request_response *req_p, | |
2235 | cy_as_ll_request_response *reply_p, | |
2236 | cy_as_storage_sd_reg_read_data *info) | |
2237 | { | |
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 | ||
2283 | cy_as_return_status_t | |
2284 | cy_as_storage_sd_register_read( | |
2285 | cy_as_device_handle handle, | |
2286 | cy_as_bus_number_t bus, | |
2287 | uint8_t device, | |
2288 | cy_as_sd_card_reg_type reg_type, | |
2289 | cy_as_storage_sd_reg_read_data *data_p, | |
2290 | cy_as_function_callback cb, | |
2291 | uint32_t client) | |
2292 | { | |
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 | ||
2381 | destroy: | |
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 | 2387 | EXPORT_SYMBOL(cy_as_storage_sd_register_read); |
81eb669b DC |
2388 | |
2389 | cy_as_return_status_t | |
2390 | cy_as_storage_create_p_partition( | |
2391 | /* Handle to the device of interest */ | |
2392 | cy_as_device_handle handle, | |
2393 | cy_as_bus_number_t bus, | |
2394 | uint32_t device, | |
2395 | /* of P-port only partition in blocks */ | |
2396 | uint32_t size, | |
2397 | cy_as_function_callback cb, | |
2398 | uint32_t client) | |
2399 | { | |
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 | ||
2458 | destroy: | |
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 | 2464 | EXPORT_SYMBOL(cy_as_storage_create_p_partition); |
81eb669b DC |
2465 | |
2466 | cy_as_return_status_t | |
2467 | cy_as_storage_remove_p_partition( | |
2468 | cy_as_device_handle handle, | |
2469 | cy_as_bus_number_t bus, | |
2470 | uint32_t device, | |
2471 | cy_as_function_callback cb, | |
2472 | uint32_t client) | |
2473 | { | |
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 | ||
2528 | destroy: | |
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 | 2534 | EXPORT_SYMBOL(cy_as_storage_remove_p_partition); |
81eb669b DC |
2535 | |
2536 | static cy_as_return_status_t | |
2537 | my_handle_response_get_transfer_amount(cy_as_device *dev_p, | |
2538 | cy_as_ll_request_response *req_p, | |
2539 | cy_as_ll_request_response *reply_p, | |
2540 | cy_as_m_s_c_progress_data *data) | |
2541 | { | |
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 | |
2559 | destroy: | |
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 | ||
2566 | cy_as_return_status_t | |
2567 | cy_as_storage_get_transfer_amount( | |
2568 | cy_as_device_handle handle, | |
2569 | cy_as_bus_number_t bus, | |
2570 | uint32_t device, | |
2571 | cy_as_m_s_c_progress_data *data_p, | |
2572 | cy_as_function_callback cb, | |
2573 | uint32_t client | |
2574 | ) | |
2575 | { | |
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 | ||
2630 | destroy: | |
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 | 2637 | EXPORT_SYMBOL(cy_as_storage_get_transfer_amount); |
81eb669b DC |
2638 | |
2639 | cy_as_return_status_t | |
2640 | cy_as_storage_erase( | |
2641 | cy_as_device_handle handle, | |
2642 | cy_as_bus_number_t bus, | |
2643 | uint32_t device, | |
2644 | uint32_t erase_unit, | |
2645 | uint16_t num_erase_units, | |
2646 | cy_as_function_callback cb, | |
2647 | uint32_t client | |
2648 | ) | |
2649 | { | |
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 | ||
2733 | destroy: | |
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 | 2739 | EXPORT_SYMBOL(cy_as_storage_erase); |
81eb669b DC |
2740 | |
2741 | static void | |
2742 | cy_as_storage_func_callback(cy_as_device *dev_p, | |
2743 | uint8_t context, | |
2744 | cy_as_ll_request_response *rqt, | |
2745 | cy_as_ll_request_response *resp, | |
2746 | cy_as_return_status_t stat) | |
2747 | { | |
2748 | cy_as_func_c_b_node *node = (cy_as_func_c_b_node *) | |
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 | ||
2855 | static void | |
2856 | cy_as_sdio_sync_reply_callback( | |
2857 | cy_as_device *dev_p, | |
2858 | uint8_t context, | |
2859 | cy_as_ll_request_response *rqt, | |
2860 | cy_as_ll_request_response *resp, | |
2861 | cy_as_return_status_t ret) | |
2862 | { | |
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 | ||
2897 | cy_as_return_status_t | |
2898 | cy_as_sdio_device_check( | |
2899 | cy_as_device *dev_p, | |
2900 | cy_as_bus_number_t bus, | |
2901 | uint32_t device) | |
2902 | { | |
2903 | if (!dev_p || (dev_p->sig != CY_AS_DEVICE_HANDLE_SIGNATURE)) | |
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 | ||
2918 | cy_as_return_status_t | |
2919 | cy_as_sdio_direct_io( | |
2920 | cy_as_device_handle handle, | |
2921 | cy_as_bus_number_t bus, | |
2922 | uint32_t device, | |
2923 | uint8_t n_function_no, | |
2924 | uint32_t address, | |
2925 | uint8_t misc_buf, | |
2926 | uint16_t argument, | |
2927 | uint8_t is_write, | |
2928 | uint8_t *data_p) | |
2929 | { | |
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 | ||
3001 | destroy: | |
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 | ||
3010 | cy_as_return_status_t | |
3011 | cy_as_sdio_direct_read( | |
3012 | cy_as_device_handle handle, | |
3013 | cy_as_bus_number_t bus, | |
3014 | uint32_t device, | |
3015 | uint8_t n_function_no, | |
3016 | uint32_t address, | |
3017 | uint8_t misc_buf, | |
3018 | uint8_t *data_p) | |
3019 | { | |
3020 | return cy_as_sdio_direct_io(handle, bus, device, n_function_no, | |
3021 | address, misc_buf, 0x00, cy_false, data_p); | |
3022 | } | |
af109f2e | 3023 | EXPORT_SYMBOL(cy_as_sdio_direct_read); |
81eb669b DC |
3024 | |
3025 | cy_as_return_status_t | |
3026 | cy_as_sdio_direct_write( | |
3027 | cy_as_device_handle handle, | |
3028 | cy_as_bus_number_t bus, | |
3029 | uint32_t device, | |
3030 | uint8_t n_function_no, | |
3031 | uint32_t address, | |
3032 | uint8_t misc_buf, | |
3033 | uint16_t argument, | |
3034 | uint8_t *data_p) | |
3035 | { | |
3036 | return cy_as_sdio_direct_io(handle, bus, device, n_function_no, | |
3037 | address, misc_buf, argument, cy_true, data_p); | |
3038 | } | |
af109f2e | 3039 | EXPORT_SYMBOL(cy_as_sdio_direct_write); |
81eb669b DC |
3040 | |
3041 | /*Cmd53 IO*/ | |
3042 | cy_as_return_status_t | |
3043 | cy_as_sdio_extended_i_o( | |
3044 | cy_as_device_handle handle, | |
3045 | cy_as_bus_number_t bus, | |
3046 | uint32_t device, | |
3047 | uint8_t n_function_no, | |
3048 | uint32_t address, | |
3049 | uint8_t misc_buf, | |
3050 | uint16_t argument, | |
3051 | uint8_t is_write, | |
3052 | uint8_t *data_p , | |
3053 | uint8_t is_resume) | |
3054 | { | |
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 | ||
3182 | static void | |
3183 | cy_as_sdio_async_reply_callback( | |
3184 | cy_as_device *dev_p, | |
3185 | uint8_t context, | |
3186 | cy_as_ll_request_response *rqt, | |
3187 | cy_as_ll_request_response *resp, | |
3188 | cy_as_return_status_t ret) | |
3189 | { | |
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 | ||
3253 | cy_as_return_status_t | |
3254 | cy_as_sdio_extended_i_o_async( | |
3255 | cy_as_device_handle handle, | |
3256 | cy_as_bus_number_t bus, | |
3257 | uint32_t device, | |
3258 | uint8_t n_function_no, | |
3259 | uint32_t address, | |
3260 | uint8_t misc_buf, | |
3261 | uint16_t argument, | |
3262 | uint8_t is_write, | |
3263 | uint8_t *data_p, | |
3264 | cy_as_storage_callback callback) | |
3265 | { | |
3266 | ||
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*/ | |
3402 | cy_as_return_status_t | |
3403 | cy_as_sdio_extended_read( | |
3404 | cy_as_device_handle handle, | |
3405 | cy_as_bus_number_t bus, | |
3406 | uint32_t device, | |
3407 | uint8_t n_function_no, | |
3408 | uint32_t address, | |
3409 | uint8_t misc_buf, | |
3410 | uint16_t argument, | |
3411 | uint8_t *data_p, | |
3412 | cy_as_sdio_callback callback) | |
3413 | { | |
3414 | if (callback == 0) | |
3415 | return cy_as_sdio_extended_i_o(handle, bus, device, | |
3416 | n_function_no, address, misc_buf, argument, | |
3417 | cy_false, data_p, 0); | |
3418 | ||
3419 | return cy_as_sdio_extended_i_o_async(handle, bus, device, | |
3420 | n_function_no, address, misc_buf, argument, cy_false, | |
3421 | data_p, callback); | |
3422 | } | |
af109f2e | 3423 | EXPORT_SYMBOL(cy_as_sdio_extended_read); |
81eb669b DC |
3424 | |
3425 | /* CMD53 Extended Write*/ | |
3426 | cy_as_return_status_t | |
3427 | cy_as_sdio_extended_write( | |
3428 | cy_as_device_handle handle, | |
3429 | cy_as_bus_number_t bus, | |
3430 | uint32_t device, | |
3431 | uint8_t n_function_no, | |
3432 | uint32_t address, | |
3433 | uint8_t misc_buf, | |
3434 | uint16_t argument, | |
3435 | uint8_t *data_p, | |
3436 | cy_as_sdio_callback callback) | |
3437 | { | |
3438 | if (callback == 0) | |
3439 | return cy_as_sdio_extended_i_o(handle, bus, device, | |
3440 | n_function_no, address, misc_buf, argument, cy_true, | |
3441 | data_p, 0); | |
3442 | ||
3443 | return cy_as_sdio_extended_i_o_async(handle, bus, device, | |
3444 | n_function_no, address, misc_buf, argument, cy_true, | |
3445 | data_p, callback); | |
3446 | } | |
af109f2e | 3447 | EXPORT_SYMBOL(cy_as_sdio_extended_write); |
81eb669b DC |
3448 | |
3449 | /* Read the CIS info tuples for the given function and Tuple ID*/ | |
3450 | cy_as_return_status_t | |
3451 | cy_as_sdio_get_c_i_s_info( | |
3452 | cy_as_device_handle handle, | |
3453 | cy_as_bus_number_t bus, | |
3454 | uint32_t device, | |
3455 | uint8_t n_function_no, | |
3456 | uint16_t tuple_id, | |
3457 | uint8_t *data_p) | |
3458 | { | |
3459 | ||
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*/ | |
3550 | cy_as_return_status_t | |
3551 | cy_as_sdio_query_card( | |
3552 | cy_as_device_handle handle, | |
3553 | cy_as_bus_number_t bus, | |
3554 | uint32_t device, | |
3555 | cy_as_sdio_card *data_p) | |
3556 | { | |
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 | } |
3631 | destroy: | |
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 | 3638 | EXPORT_SYMBOL(cy_as_sdio_query_card); |
81eb669b DC |
3639 | |
3640 | /*Reset SDIO card. */ | |
3641 | cy_as_return_status_t | |
3642 | cy_as_sdio_reset_card( | |
3643 | cy_as_device_handle handle, | |
3644 | cy_as_bus_number_t bus, | |
3645 | uint32_t device) | |
3646 | { | |
3647 | ||
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 | |
3694 | destroy: | |
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*/ | |
3703 | cy_as_return_status_t | |
3704 | cy_as_sdio_init_function( | |
3705 | cy_as_device_handle handle, | |
3706 | cy_as_bus_number_t bus, | |
3707 | uint32_t device, | |
3708 | uint8_t n_function_no, | |
3709 | uint8_t misc_buf) | |
3710 | { | |
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 | ||
3782 | destroy: | |
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 | 3789 | EXPORT_SYMBOL(cy_as_sdio_init_function); |
81eb669b DC |
3790 | |
3791 | /*Query individual functions. */ | |
3792 | cy_as_return_status_t | |
3793 | cy_as_sdio_query_function( | |
3794 | cy_as_device_handle handle, | |
3795 | cy_as_bus_number_t bus, | |
3796 | uint32_t device, | |
3797 | uint8_t n_function_no, | |
3798 | cy_as_sdio_func *data_p) | |
3799 | { | |
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*/ | |
3831 | cy_as_return_status_t | |
3832 | cy_as_sdio_abort_function( | |
3833 | cy_as_device_handle handle, | |
3834 | cy_as_bus_number_t bus, | |
3835 | uint32_t device, | |
3836 | uint8_t n_function_no) | |
3837 | { | |
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 | ||
3886 | destroy: | |
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*/ | |
3895 | cy_as_return_status_t | |
3896 | cy_as_sdio_suspend( | |
3897 | cy_as_device_handle handle, | |
3898 | cy_as_bus_number_t bus, | |
3899 | uint32_t device, | |
3900 | uint8_t n_function_no) | |
3901 | { | |
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*/ | |
3950 | cy_as_return_status_t | |
3951 | cy_as_sdio_resume( | |
3952 | cy_as_device_handle handle, | |
3953 | cy_as_bus_number_t bus, | |
3954 | uint32_t device, | |
3955 | uint8_t n_function_no, | |
3956 | cy_as_oper_type op, | |
3957 | uint8_t misc_buf, | |
3958 | uint16_t pendingblockcount, | |
3959 | uint8_t *data_p | |
3960 | ) | |
3961 | { | |
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 | ||
4023 | destroy: | |
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*/ | |
4035 | cy_as_return_status_t | |
4036 | cy_as_sdio_set_blocksize( | |
4037 | cy_as_device_handle handle, | |
4038 | cy_as_bus_number_t bus, | |
4039 | uint32_t device, | |
4040 | uint8_t n_function_no, | |
4041 | uint16_t blocksize) | |
4042 | { | |
4043 | cy_as_return_status_t ret; | |
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 | 4089 | EXPORT_SYMBOL(cy_as_sdio_set_blocksize); |
81eb669b DC |
4090 | |
4091 | /* Deinitialize an SDIO function*/ | |
4092 | cy_as_return_status_t | |
4093 | cy_as_sdio_de_init_function( | |
4094 | cy_as_device_handle handle, | |
4095 | cy_as_bus_number_t bus, | |
4096 | uint32_t device, | |
4097 | uint8_t n_function_no) | |
4098 | { | |
4099 | cy_as_return_status_t ret; | |
4100 | uint8_t temp; | |
4101 | ||
4102 | if (n_function_no == 0) | |
4103 | return CY_AS_ERROR_INVALID_FUNCTION; | |
4104 | ||
4105 | ret = cy_as_sdio_device_check((cy_as_device *)handle, bus, device); | |
4106 | if (ret != CY_AS_ERROR_SUCCESS) | |
4107 | return ret; | |
4108 | ||
4109 | if (!(cy_as_sdio_check_function_initialized | |
4110 | (handle, bus, n_function_no))) | |
4111 | return CY_AS_ERROR_SUCCESS; | |
4112 | ||
4113 | temp = (uint8_t)(((cy_as_device *)handle)->sdiocard[bus]. | |
4114 | function_init_map & (~(1 << n_function_no))); | |
4115 | ||
4116 | cy_as_sdio_direct_write(handle, bus, device, 0, 0x02, 0, temp, 0); | |
4117 | ||
4118 | ((cy_as_device *)handle)->sdiocard[bus].function_init_map &= | |
4119 | (~(1 << n_function_no)); | |
4120 | ||
4121 | return CY_AS_ERROR_SUCCESS; | |
4122 | } | |
4123 | ||
4124 | ||
4125 | /*[]*/ |