1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "../../include/linux/westbridge/cyashal.h"
23#include "../../include/linux/westbridge/cyascast.h"
24#include "../../include/linux/westbridge/cyasdevice.h"
25#include "../../include/linux/westbridge/cyaslowlevel.h"
26#include "../../include/linux/westbridge/cyasintr.h"
27#include "../../include/linux/westbridge/cyaserr.h"
28#include "../../include/linux/westbridge/cyasregs.h"
29
30static const uint32_t cy_as_low_level_timeout_count = 65536 * 4;
31
32
33static cy_as_return_status_t cy_as_send_one(cy_as_device *dev_p,
34 cy_as_ll_request_response *req_p);
35
36
37
38
39
40
41
42static uint16_t max_request_length[CY_RQT_CONTEXT_COUNT] = {
43 8,
44 8,
45 8,
46 128,
47 8
48};
49
50
51
52
53
54
55
56static void
57cy_as_ll_remove_request_queue_head(cy_as_device *dev_p, cy_as_context *ctxt_p)
58{
59 uint32_t mask, state;
60 cy_as_ll_request_list_node *node_p;
61
62 (void)dev_p;
63 cy_as_hal_assert(ctxt_p->request_queue_p != 0);
64
65 mask = cy_as_hal_disable_interrupts();
66 node_p = ctxt_p->request_queue_p;
67 ctxt_p->request_queue_p = node_p->next;
68 cy_as_hal_enable_interrupts(mask);
69
70 node_p->callback = 0;
71 node_p->rqt = 0;
72 node_p->resp = 0;
73
74
75
76
77
78
79
80
81
82
83 state = cy_as_hal_disable_interrupts();
84 cy_as_hal_c_b_free(node_p);
85 cy_as_hal_enable_interrupts(state);
86}
87
88
89
90
91
92
93static void
94cy_as_ll_send_next_request(cy_as_device *dev_p, cy_as_context *ctxt_p)
95{
96 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
97
98
99
100
101
102 while (ret == ret) {
103 cy_as_ll_request_list_node *node_p = ctxt_p->request_queue_p;
104 if (node_p == 0)
105 break;
106
107 if (cy_as_request_get_node_state(node_p) !=
108 CY_AS_REQUEST_LIST_STATE_QUEUED)
109 break;
110
111 cy_as_request_set_node_state(node_p,
112 CY_AS_REQUEST_LIST_STATE_WAITING);
113 ret = cy_as_send_one(dev_p, node_p->rqt);
114 if (ret == CY_AS_ERROR_SUCCESS)
115 break;
116
117
118
119
120
121 cy_as_request_set_node_state(node_p,
122 CY_AS_REQUEST_LIST_STATE_RECEIVED);
123 node_p->callback(dev_p, ctxt_p->number,
124 node_p->rqt, node_p->resp, ret);
125 cy_as_ll_remove_request_queue_head(dev_p, ctxt_p);
126
127
128
129
130
131 }
132}
133
134
135
136
137
138cy_as_remove_request_result_t
139cy_as_ll_remove_request(cy_as_device *dev_p, cy_as_context *ctxt_p,
140 cy_as_ll_request_response *req_p, cy_bool force)
141{
142 uint32_t imask;
143 cy_as_ll_request_list_node *node_p;
144 cy_as_ll_request_list_node *tmp_p;
145 uint32_t state;
146
147 imask = cy_as_hal_disable_interrupts();
148 if (ctxt_p->request_queue_p != 0 &&
149 ctxt_p->request_queue_p->rqt == req_p) {
150 node_p = ctxt_p->request_queue_p;
151 if ((cy_as_request_get_node_state(node_p) ==
152 CY_AS_REQUEST_LIST_STATE_WAITING) && (!force)) {
153 cy_as_hal_enable_interrupts(imask);
154 return cy_as_remove_request_in_transit;
155 }
156
157 ctxt_p->request_queue_p = node_p->next;
158 } else {
159 tmp_p = ctxt_p->request_queue_p;
160 while (tmp_p != 0 && tmp_p->next != 0 &&
161 tmp_p->next->rqt != req_p)
162 tmp_p = tmp_p->next;
163
164 if (tmp_p == 0 || tmp_p->next == 0) {
165 cy_as_hal_enable_interrupts(imask);
166 return cy_as_remove_request_not_found;
167 }
168
169 node_p = tmp_p->next;
170 tmp_p->next = node_p->next;
171 }
172
173 if (node_p->callback)
174 node_p->callback(dev_p, ctxt_p->number, node_p->rqt,
175 node_p->resp, CY_AS_ERROR_CANCELED);
176
177 state = cy_as_hal_disable_interrupts();
178 cy_as_hal_c_b_free(node_p);
179 cy_as_hal_enable_interrupts(state);
180
181 cy_as_hal_enable_interrupts(imask);
182 return cy_as_remove_request_sucessful;
183}
184
185void
186cy_as_ll_remove_all_requests(cy_as_device *dev_p, cy_as_context *ctxt_p)
187{
188 cy_as_ll_request_list_node *node = ctxt_p->request_queue_p;
189
190 while (node) {
191 if (cy_as_request_get_node_state(ctxt_p->request_queue_p) !=
192 CY_AS_REQUEST_LIST_STATE_RECEIVED)
193 cy_as_ll_remove_request(dev_p, ctxt_p,
194 node->rqt, cy_true);
195 node = node->next;
196 }
197}
198
199static cy_bool
200cy_as_ll_is_in_queue(cy_as_context *ctxt_p, cy_as_ll_request_response *req_p)
201{
202 uint32_t mask;
203 cy_as_ll_request_list_node *node_p;
204
205 mask = cy_as_hal_disable_interrupts();
206 node_p = ctxt_p->request_queue_p;
207 while (node_p) {
208 if (node_p->rqt == req_p) {
209 cy_as_hal_enable_interrupts(mask);
210 return cy_true;
211 }
212 node_p = node_p->next;
213 }
214 cy_as_hal_enable_interrupts(mask);
215 return cy_false;
216}
217
218
219
220
221
222
223
224
225
226void
227cy_as_ll_queue_mailbox_data(cy_as_device *dev_p)
228{
229 cy_as_context *ctxt_p;
230 uint8_t context;
231 uint16_t data[4];
232 int32_t i;
233
234
235 for (i = 3; i >= 0; i--)
236 data[i] = cy_as_hal_read_register(dev_p->tag,
237 cy_cast_int2U_int16(CY_AS_MEM_P0_MAILBOX0 + i));
238
239 context = cy_as_mbox_get_context(data[0]);
240 if (context >= CY_RQT_CONTEXT_COUNT) {
241 cy_as_hal_print_message("mailbox request/response received "
242 "with invalid context value (%d)\n", context);
243 return;
244 }
245
246 ctxt_p = dev_p->context[context];
247
248
249
250
251 cy_as_hal_assert(ctxt_p->queue_index * sizeof(uint16_t) +
252 sizeof(data) <= sizeof(ctxt_p->data_queue));
253
254 for (i = 0; i < 4; i++)
255 ctxt_p->data_queue[ctxt_p->queue_index++] = data[i];
256
257 cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
258 dev_p->ll_queued_data = cy_true;
259}
260
261void
262cy_as_mail_box_process_data(cy_as_device *dev_p, uint16_t *data)
263{
264 cy_as_context *ctxt_p;
265 uint8_t context;
266 uint16_t *len_p;
267 cy_as_ll_request_response *rec_p;
268 uint8_t st;
269 uint16_t src, dest;
270
271 context = cy_as_mbox_get_context(data[0]);
272 if (context >= CY_RQT_CONTEXT_COUNT) {
273 cy_as_hal_print_message("mailbox request/response received "
274 "with invalid context value (%d)\n", context);
275 return;
276 }
277
278 ctxt_p = dev_p->context[context];
279
280 if (cy_as_mbox_is_request(data[0])) {
281 cy_as_hal_assert(ctxt_p->req_p != 0);
282 rec_p = ctxt_p->req_p;
283 len_p = &ctxt_p->request_length;
284
285 } else {
286 if (ctxt_p->request_queue_p == 0 ||
287 cy_as_request_get_node_state(ctxt_p->request_queue_p)
288 != CY_AS_REQUEST_LIST_STATE_WAITING) {
289 cy_as_hal_print_message("mailbox response received on "
290 "context that was not expecting a response\n");
291 cy_as_hal_print_message(" context: %d\n", context);
292 cy_as_hal_print_message(" contents: 0x%04x 0x%04x "
293 "0x%04x 0x%04x\n",
294 data[0], data[1], data[2], data[3]);
295 if (ctxt_p->request_queue_p != 0)
296 cy_as_hal_print_message(" state: 0x%02x\n",
297 ctxt_p->request_queue_p->state);
298 return;
299 }
300
301
302 cy_as_hal_assert(ctxt_p->request_queue_p->resp != 0);
303
304 rec_p = ctxt_p->request_queue_p->resp;
305 len_p = &ctxt_p->request_queue_p->length;
306 }
307
308 if (rec_p->stored == 0) {
309
310
311
312 cy_as_ll_request_response__set_code(rec_p,
313 cy_as_mbox_get_code(data[0]));
314 cy_as_ll_request_response__set_context(rec_p, context);
315
316 if (cy_as_mbox_is_last(data[0])) {
317
318 *len_p = rec_p->length;
319 st = 1;
320 } else {
321
322
323 cy_as_hal_assert(rec_p->length >= data[1]);
324 *len_p = (data[1] < rec_p->length) ?
325 data[1] : rec_p->length;
326 st = 2;
327 }
328 } else
329 st = 1;
330
331
332 while (rec_p->stored < *len_p && st < 4)
333 rec_p->data[rec_p->stored++] = data[st++];
334
335 if (cy_as_mbox_is_last(data[0])) {
336
337
338
339
340
341
342
343
344 if ((ctxt_p->rqt_index > 0) &&
345 (ctxt_p->rqt_index <= ctxt_p->queue_index)) {
346 dest = 0;
347 src = ctxt_p->rqt_index;
348
349 while (src < ctxt_p->queue_index)
350 ctxt_p->data_queue[dest++] =
351 ctxt_p->data_queue[src++];
352
353 ctxt_p->rqt_index = 0;
354 ctxt_p->queue_index = dest;
355 cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
356 }
357
358 if (ctxt_p->request_queue_p != 0 && rec_p ==
359 ctxt_p->request_queue_p->resp) {
360
361
362
363
364 cy_as_ll_request_response *resp_p =
365 ctxt_p->request_queue_p->resp;
366 resp_p->length = ctxt_p->request_queue_p->length;
367 cy_as_request_set_node_state(ctxt_p->request_queue_p,
368 CY_AS_REQUEST_LIST_STATE_RECEIVED);
369
370 cy_as_device_set_in_callback(dev_p);
371 ctxt_p->request_queue_p->callback(dev_p, context,
372 ctxt_p->request_queue_p->rqt,
373 resp_p, CY_AS_ERROR_SUCCESS);
374
375 cy_as_device_clear_in_callback(dev_p);
376
377 cy_as_ll_remove_request_queue_head(dev_p, ctxt_p);
378 cy_as_ll_send_next_request(dev_p, ctxt_p);
379 } else {
380
381
382 cy_as_ll_request_response *request_p = ctxt_p->req_p;
383 ctxt_p->req_p = 0;
384 if (ctxt_p->request_callback) {
385 cy_as_device_set_in_callback(dev_p);
386 ctxt_p->request_callback(dev_p, context,
387 request_p, 0, CY_AS_ERROR_SUCCESS);
388 cy_as_device_clear_in_callback(dev_p);
389 }
390 cy_as_ll_init_request(request_p, 0,
391 context, request_p->length);
392 ctxt_p->req_p = request_p;
393 }
394 }
395}
396
397
398
399
400void
401cy_as_mail_box_queued_data_handler(cy_as_device *dev_p)
402{
403 uint16_t i;
404
405
406
407
408
409
410 while (dev_p->ll_queued_data) {
411 dev_p->ll_queued_data = cy_false;
412 for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
413 uint16_t offset;
414 cy_as_context *ctxt_p = dev_p->context[i];
415 cy_as_hal_assert((ctxt_p->queue_index % 4) == 0);
416
417 offset = 0;
418 while (offset < ctxt_p->queue_index) {
419 ctxt_p->rqt_index = offset + 4;
420 cy_as_mail_box_process_data(dev_p,
421 ctxt_p->data_queue + offset);
422 offset = ctxt_p->rqt_index;
423 }
424 ctxt_p->queue_index = 0;
425 }
426 }
427}
428
429
430
431
432
433
434
435
436
437void
438cy_as_mail_box_interrupt_handler(cy_as_device *dev_p)
439{
440 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
441
442
443
444
445
446 cy_as_ll_queue_mailbox_data(dev_p);
447
448
449
450
451 cy_as_mail_box_queued_data_handler(dev_p);
452}
453
454cy_as_return_status_t
455cy_as_ll_start(cy_as_device *dev_p)
456{
457 uint16_t i;
458
459 if (cy_as_device_is_low_level_running(dev_p))
460 return CY_AS_ERROR_ALREADY_RUNNING;
461
462 dev_p->ll_sending_rqt = cy_false;
463 dev_p->ll_abort_curr_rqt = cy_false;
464
465 for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
466 dev_p->context[i] = (cy_as_context *)
467 cy_as_hal_alloc(sizeof(cy_as_context));
468 if (dev_p->context[i] == 0)
469 return CY_AS_ERROR_OUT_OF_MEMORY;
470
471 dev_p->context[i]->number = (uint8_t)i;
472 dev_p->context[i]->request_callback = 0;
473 dev_p->context[i]->request_queue_p = 0;
474 dev_p->context[i]->last_node_p = 0;
475 dev_p->context[i]->req_p = cy_as_ll_create_request(dev_p,
476 0, (uint8_t)i, max_request_length[i]);
477 dev_p->context[i]->queue_index = 0;
478
479 if (!cy_as_hal_create_sleep_channel
480 (&dev_p->context[i]->channel))
481 return CY_AS_ERROR_CREATE_SLEEP_CHANNEL_FAILED;
482 }
483
484 cy_as_device_set_low_level_running(dev_p);
485 return CY_AS_ERROR_SUCCESS;
486}
487
488
489
490
491
492cy_as_return_status_t
493cy_as_ll_stop(cy_as_device *dev_p)
494{
495 uint8_t i;
496 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
497 cy_as_context *ctxt_p;
498 uint32_t mask;
499
500 for (i = 0; i < CY_RQT_CONTEXT_COUNT; i++) {
501 ctxt_p = dev_p->context[i];
502 if (!cy_as_hal_destroy_sleep_channel(&ctxt_p->channel))
503 return CY_AS_ERROR_DESTROY_SLEEP_CHANNEL_FAILED;
504
505
506
507
508 while (ctxt_p->request_queue_p) {
509 uint32_t state;
510 cy_as_ll_request_list_node *node_p =
511 ctxt_p->request_queue_p;
512
513
514 cy_as_request_set_node_state(node_p,
515 CY_AS_REQUEST_LIST_STATE_CANCELING);
516
517
518
519
520
521
522 node_p->callback(dev_p, i, node_p->rqt,
523 node_p->resp, CY_AS_ERROR_CANCELED);
524
525
526 mask = cy_as_hal_disable_interrupts();
527 ctxt_p->request_queue_p = node_p->next;
528 cy_as_hal_enable_interrupts(mask);
529
530
531 state = cy_as_hal_disable_interrupts();
532 cy_as_hal_c_b_free(node_p);
533 cy_as_hal_enable_interrupts(state);
534 }
535
536 cy_as_ll_destroy_request(dev_p, dev_p->context[i]->req_p);
537 cy_as_hal_free(dev_p->context[i]);
538 dev_p->context[i] = 0;
539
540 }
541 cy_as_device_set_low_level_stopped(dev_p);
542
543 return ret;
544}
545
546void
547cy_as_ll_init_request(cy_as_ll_request_response *req_p,
548 uint16_t code, uint16_t context, uint16_t length)
549{
550 uint16_t totallen = sizeof(cy_as_ll_request_response) +
551 (length - 1) * sizeof(uint16_t);
552
553 cy_as_hal_mem_set(req_p, 0, totallen);
554 req_p->length = length;
555 cy_as_ll_request_response__set_code(req_p, code);
556 cy_as_ll_request_response__set_context(req_p, context);
557 cy_as_ll_request_response__set_request(req_p);
558}
559
560
561
562
563cy_as_ll_request_response *
564cy_as_ll_create_request(cy_as_device *dev_p, uint16_t code,
565 uint8_t context, uint16_t length)
566{
567 cy_as_ll_request_response *req_p;
568 uint32_t state;
569 uint16_t totallen = sizeof(cy_as_ll_request_response) +
570 (length - 1) * sizeof(uint16_t);
571
572 (void)dev_p;
573
574 state = cy_as_hal_disable_interrupts();
575 req_p = cy_as_hal_c_b_alloc(totallen);
576 cy_as_hal_enable_interrupts(state);
577 if (req_p)
578 cy_as_ll_init_request(req_p, code, context, length);
579
580 return req_p;
581}
582
583
584
585
586void
587cy_as_ll_destroy_request(cy_as_device *dev_p, cy_as_ll_request_response *req_p)
588{
589 uint32_t state;
590 (void)dev_p;
591 (void)req_p;
592
593 state = cy_as_hal_disable_interrupts();
594 cy_as_hal_c_b_free(req_p);
595 cy_as_hal_enable_interrupts(state);
596
597}
598
599void
600cy_as_ll_init_response(cy_as_ll_request_response *req_p, uint16_t length)
601{
602 uint16_t totallen = sizeof(cy_as_ll_request_response) +
603 (length - 1) * sizeof(uint16_t);
604
605 cy_as_hal_mem_set(req_p, 0, totallen);
606 req_p->length = length;
607 cy_as_ll_request_response__set_response(req_p);
608}
609
610
611
612
613cy_as_ll_request_response *
614cy_as_ll_create_response(cy_as_device *dev_p, uint16_t length)
615{
616 cy_as_ll_request_response *req_p;
617 uint32_t state;
618 uint16_t totallen = sizeof(cy_as_ll_request_response) +
619 (length - 1) * sizeof(uint16_t);
620
621 (void)dev_p;
622
623 state = cy_as_hal_disable_interrupts();
624 req_p = cy_as_hal_c_b_alloc(totallen);
625 cy_as_hal_enable_interrupts(state);
626 if (req_p)
627 cy_as_ll_init_response(req_p, length);
628
629 return req_p;
630}
631
632
633
634
635void
636cy_as_ll_destroy_response(cy_as_device *dev_p, cy_as_ll_request_response *req_p)
637{
638 uint32_t state;
639 (void)dev_p;
640 (void)req_p;
641
642 state = cy_as_hal_disable_interrupts();
643 cy_as_hal_c_b_free(req_p);
644 cy_as_hal_enable_interrupts(state);
645}
646
647static uint16_t
648cy_as_read_intr_status(
649 cy_as_device *dev_p)
650{
651 uint32_t mask;
652 cy_bool bloop = cy_true;
653 uint16_t v = 0, last = 0xffff;
654
655
656
657
658
659
660
661 while (last == last) {
662
663
664
665
666
667 mask = cy_as_hal_disable_interrupts();
668
669
670
671
672 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG);
673 if ((v & CY_AS_MEM_P0_INTR_REG_MBINT) == 0) {
674 cy_as_hal_enable_interrupts(mask);
675 break;
676 }
677
678
679
680
681
682
683 cy_as_ll_queue_mailbox_data(dev_p);
684
685
686
687
688
689 cy_as_hal_enable_interrupts(mask);
690 }
691
692
693
694
695 last = cy_as_hal_read_register(dev_p->tag,
696 CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD;
697 while (bloop) {
698 v = cy_as_hal_read_register(dev_p->tag,
699 CY_AS_MEM_MCU_MB_STAT) & CY_AS_MEM_P0_MCU_MBNOTRD;
700 if (v == last)
701 break;
702
703 last = v;
704 }
705
706 return v;
707}
708
709
710
711
712
713
714static cy_as_return_status_t
715cy_as_send_one(
716 cy_as_device *dev_p,
717 cy_as_ll_request_response *req_p)
718{
719 int i;
720 uint16_t mb0, v;
721 int32_t loopcount;
722 uint32_t int_stat;
723
724#ifdef _DEBUG
725 if (cy_as_ll_request_response__is_request(req_p)) {
726 switch (cy_as_ll_request_response__get_context(req_p)) {
727 case CY_RQT_GENERAL_RQT_CONTEXT:
728 cy_as_hal_assert(req_p->length * 2 + 2 <
729 CY_CTX_GEN_MAX_DATA_SIZE);
730 break;
731
732 case CY_RQT_RESOURCE_RQT_CONTEXT:
733 cy_as_hal_assert(req_p->length * 2 + 2 <
734 CY_CTX_RES_MAX_DATA_SIZE);
735 break;
736
737 case CY_RQT_STORAGE_RQT_CONTEXT:
738 cy_as_hal_assert(req_p->length * 2 + 2 <
739 CY_CTX_STR_MAX_DATA_SIZE);
740 break;
741
742 case CY_RQT_USB_RQT_CONTEXT:
743 cy_as_hal_assert(req_p->length * 2 + 2 <
744 CY_CTX_USB_MAX_DATA_SIZE);
745 break;
746 }
747 }
748#endif
749
750
751 if (req_p->length > 3) {
752 uint16_t length = req_p->length;
753 int which = 0;
754 int st = 1;
755
756 dev_p->ll_sending_rqt = cy_true;
757 while (which < length) {
758 loopcount = cy_as_low_level_timeout_count;
759 do {
760 v = cy_as_read_intr_status(dev_p);
761
762 } while (v && loopcount-- > 0);
763
764 if (v) {
765 cy_as_hal_print_message(
766 ">>>>>> LOW LEVEL TIMEOUT "
767 "%x %x %x %x\n",
768 cy_as_hal_read_register(dev_p->tag,
769 CY_AS_MEM_MCU_MAILBOX0),
770 cy_as_hal_read_register(dev_p->tag,
771 CY_AS_MEM_MCU_MAILBOX1),
772 cy_as_hal_read_register(dev_p->tag,
773 CY_AS_MEM_MCU_MAILBOX2),
774 cy_as_hal_read_register(dev_p->tag,
775 CY_AS_MEM_MCU_MAILBOX3));
776 return CY_AS_ERROR_TIMEOUT;
777 }
778
779 if (dev_p->ll_abort_curr_rqt) {
780 dev_p->ll_sending_rqt = cy_false;
781 dev_p->ll_abort_curr_rqt = cy_false;
782 return CY_AS_ERROR_CANCELED;
783 }
784
785 int_stat = cy_as_hal_disable_interrupts();
786
787
788
789
790
791
792
793 v = cy_as_hal_read_register(dev_p->tag,
794 CY_AS_MEM_MCU_MB_STAT) &
795 CY_AS_MEM_P0_MCU_MBNOTRD;
796 if (v) {
797
798
799 cy_as_hal_enable_interrupts(int_stat);
800 continue;
801 }
802
803 if (which == 0) {
804 cy_as_hal_write_register(dev_p->tag,
805 CY_AS_MEM_MCU_MAILBOX1, length);
806 st = 2;
807 } else {
808 st = 1;
809 }
810
811 while ((which < length) && (st < 4)) {
812 cy_as_hal_write_register(dev_p->tag,
813 cy_cast_int2U_int16
814 (CY_AS_MEM_MCU_MAILBOX0 + st),
815 req_p->data[which++]);
816 st++;
817 }
818
819 mb0 = req_p->box0;
820 if (which == length) {
821 dev_p->ll_sending_rqt = cy_false;
822 mb0 |= CY_AS_REQUEST_RESPONSE_LAST_MASK;
823 }
824
825 if (dev_p->ll_abort_curr_rqt) {
826 dev_p->ll_sending_rqt = cy_false;
827 dev_p->ll_abort_curr_rqt = cy_false;
828 cy_as_hal_enable_interrupts(int_stat);
829 return CY_AS_ERROR_CANCELED;
830 }
831
832 cy_as_hal_write_register(dev_p->tag,
833 CY_AS_MEM_MCU_MAILBOX0, mb0);
834
835
836 cy_as_hal_sleep150();
837 cy_as_hal_enable_interrupts(int_stat);
838 }
839 } else {
840check_mailbox_availability:
841
842
843
844
845
846
847 loopcount = cy_as_low_level_timeout_count;
848 do {
849 v = cy_as_read_intr_status(dev_p);
850
851 } while (v && loopcount-- > 0);
852
853 if (v) {
854 cy_as_hal_print_message(
855 ">>>>>> LOW LEVEL TIMEOUT %x %x %x %x\n",
856 cy_as_hal_read_register(dev_p->tag,
857 CY_AS_MEM_MCU_MAILBOX0),
858 cy_as_hal_read_register(dev_p->tag,
859 CY_AS_MEM_MCU_MAILBOX1),
860 cy_as_hal_read_register(dev_p->tag,
861 CY_AS_MEM_MCU_MAILBOX2),
862 cy_as_hal_read_register(dev_p->tag,
863 CY_AS_MEM_MCU_MAILBOX3));
864 return CY_AS_ERROR_TIMEOUT;
865 }
866
867 int_stat = cy_as_hal_disable_interrupts();
868
869
870
871
872
873
874 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_MCU_MB_STAT) &
875 CY_AS_MEM_P0_MCU_MBNOTRD;
876 if (v) {
877
878
879 cy_as_hal_enable_interrupts(int_stat);
880 goto check_mailbox_availability;
881 }
882
883
884
885 v = 0;
886 for (i = req_p->length - 1; i >= 0; i--)
887 cy_as_hal_write_register(dev_p->tag,
888 cy_cast_int2U_int16(CY_AS_MEM_MCU_MAILBOX1 + i),
889 req_p->data[i]);
890
891
892 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_MCU_MAILBOX0,
893 req_p->box0 | CY_AS_REQUEST_RESPONSE_LAST_MASK);
894
895 cy_as_hal_sleep150();
896 cy_as_hal_enable_interrupts(int_stat);
897 }
898
899 return CY_AS_ERROR_SUCCESS;
900}
901
902
903
904
905extern cy_as_return_status_t
906cy_as_ll_send_request(
907 cy_as_device *dev_p,
908
909 cy_as_ll_request_response *req,
910
911
912 cy_as_ll_request_response *resp,
913
914 cy_bool sync,
915
916 cy_as_response_callback cb
917)
918{
919 cy_as_context *ctxt_p;
920 uint16_t box0 = req->box0;
921 uint8_t context;
922 cy_as_return_status_t ret = CY_AS_ERROR_SUCCESS;
923 cy_as_ll_request_list_node *node_p;
924 uint32_t mask, state;
925
926 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
927
928 context = cy_as_mbox_get_context(box0);
929 cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
930 ctxt_p = dev_p->context[context];
931
932
933 state = cy_as_hal_disable_interrupts();
934 node_p = cy_as_hal_c_b_alloc(sizeof(cy_as_ll_request_list_node));
935 cy_as_hal_enable_interrupts(state);
936
937 if (node_p == 0)
938 return CY_AS_ERROR_OUT_OF_MEMORY;
939
940
941 node_p->callback = cb;
942 node_p->length = 0;
943 node_p->next = 0;
944 node_p->resp = resp;
945 node_p->rqt = req;
946 node_p->state = CY_AS_REQUEST_LIST_STATE_QUEUED;
947 if (sync)
948 cy_as_request_node_set_sync(node_p);
949
950
951 mask = cy_as_hal_disable_interrupts();
952 if (ctxt_p->request_queue_p == 0) {
953
954 ctxt_p->request_queue_p = node_p;
955 ctxt_p->last_node_p = node_p;
956 } else {
957 ctxt_p->last_node_p->next = node_p;
958 ctxt_p->last_node_p = node_p;
959 }
960 cy_as_hal_enable_interrupts(mask);
961 cy_as_ll_send_next_request(dev_p, ctxt_p);
962
963 if (!cy_as_device_is_in_callback(dev_p)) {
964 mask = cy_as_hal_disable_interrupts();
965 cy_as_mail_box_queued_data_handler(dev_p);
966 cy_as_hal_enable_interrupts(mask);
967 }
968
969 return ret;
970}
971
972static void
973cy_as_ll_send_callback(
974 cy_as_device *dev_p,
975 uint8_t context,
976 cy_as_ll_request_response *rqt,
977 cy_as_ll_request_response *resp,
978 cy_as_return_status_t ret)
979{
980 (void)rqt;
981 (void)resp;
982 (void)ret;
983
984
985 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
986
987
988
989
990 dev_p->ll_error = ret;
991
992
993
994
995 cy_as_hal_wake(&dev_p->context[context]->channel);
996}
997
998cy_as_return_status_t
999cy_as_ll_send_request_wait_reply(
1000 cy_as_device *dev_p,
1001
1002 cy_as_ll_request_response *req,
1003
1004
1005 cy_as_ll_request_response *resp
1006 )
1007{
1008 cy_as_return_status_t ret;
1009 uint8_t context;
1010
1011
1012 uint32_t loopcount = 800;
1013 cy_as_context *ctxt_p;
1014
1015
1016 context = cy_as_ll_request_response__get_context(req);
1017 cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
1018 ctxt_p = dev_p->context[context];
1019
1020 ret = cy_as_ll_send_request(dev_p, req, resp,
1021 cy_true, cy_as_ll_send_callback);
1022 if (ret != CY_AS_ERROR_SUCCESS)
1023 return ret;
1024
1025 while (loopcount-- > 0) {
1026
1027
1028
1029
1030
1031
1032 cy_as_hal_sleep_on(&ctxt_p->channel, 10);
1033
1034
1035
1036
1037
1038
1039 if (!cy_as_ll_is_in_queue(ctxt_p, req))
1040 return dev_p->ll_error;
1041 }
1042
1043
1044 cy_as_ll_remove_request(dev_p, ctxt_p, req, cy_true);
1045
1046 return CY_AS_ERROR_TIMEOUT;
1047}
1048
1049cy_as_return_status_t
1050cy_as_ll_register_request_callback(
1051 cy_as_device *dev_p,
1052 uint8_t context,
1053 cy_as_response_callback cb)
1054{
1055 cy_as_context *ctxt_p;
1056 cy_as_hal_assert(context < CY_RQT_CONTEXT_COUNT);
1057 ctxt_p = dev_p->context[context];
1058
1059 ctxt_p->request_callback = cb;
1060 return CY_AS_ERROR_SUCCESS;
1061}
1062
1063void
1064cy_as_ll_request_response__pack(
1065 cy_as_ll_request_response *req_p,
1066 uint32_t offset,
1067 uint32_t length,
1068 void *data_p)
1069{
1070 uint16_t dt;
1071 uint8_t *dp = (uint8_t *)data_p;
1072
1073 while (length > 1) {
1074 dt = ((*dp++) << 8);
1075 dt |= (*dp++);
1076 cy_as_ll_request_response__set_word(req_p, offset, dt);
1077 offset++;
1078 length -= 2;
1079 }
1080
1081 if (length == 1) {
1082 dt = (*dp << 8);
1083 cy_as_ll_request_response__set_word(req_p, offset, dt);
1084 }
1085}
1086
1087void
1088cy_as_ll_request_response__unpack(
1089 cy_as_ll_request_response *req_p,
1090 uint32_t offset,
1091 uint32_t length,
1092 void *data_p)
1093{
1094 uint8_t *dp = (uint8_t *)data_p;
1095
1096 while (length-- > 0) {
1097 uint16_t val = cy_as_ll_request_response__get_word
1098 (req_p, offset++);
1099 *dp++ = (uint8_t)((val >> 8) & 0xff);
1100
1101 if (length) {
1102 length--;
1103 *dp++ = (uint8_t)(val & 0xff);
1104 }
1105 }
1106}
1107
1108extern cy_as_return_status_t
1109cy_as_ll_send_status_response(
1110 cy_as_device *dev_p,
1111 uint8_t context,
1112 uint16_t code,
1113 uint8_t clear_storage)
1114{
1115 cy_as_return_status_t ret;
1116 cy_as_ll_request_response resp;
1117 cy_as_ll_request_response *resp_p = &resp;
1118
1119 cy_as_hal_mem_set(resp_p, 0, sizeof(resp));
1120 resp_p->length = 1;
1121 cy_as_ll_request_response__set_response(resp_p);
1122 cy_as_ll_request_response__set_context(resp_p, context);
1123
1124 if (clear_storage)
1125 cy_as_ll_request_response__set_clear_storage_flag(resp_p);
1126
1127 cy_as_ll_request_response__set_code(resp_p, CY_RESP_SUCCESS_FAILURE);
1128 cy_as_ll_request_response__set_word(resp_p, 0, code);
1129
1130 ret = cy_as_send_one(dev_p, resp_p);
1131
1132 return ret;
1133}
1134
1135extern cy_as_return_status_t
1136cy_as_ll_send_data_response(
1137 cy_as_device *dev_p,
1138 uint8_t context,
1139 uint16_t code,
1140 uint16_t length,
1141 void *data)
1142{
1143 cy_as_ll_request_response *resp_p;
1144 uint16_t wlen;
1145 uint8_t respbuf[256];
1146
1147 if (length > 192)
1148 return CY_AS_ERROR_INVALID_SIZE;
1149
1150
1151 wlen = length / 2;
1152
1153
1154 if (length % 2)
1155 wlen++;
1156
1157
1158 wlen++;
1159
1160 resp_p = (cy_as_ll_request_response *)respbuf;
1161 cy_as_hal_mem_set(resp_p, 0, sizeof(respbuf));
1162 resp_p->length = wlen;
1163 cy_as_ll_request_response__set_context(resp_p, context);
1164 cy_as_ll_request_response__set_code(resp_p, code);
1165
1166 cy_as_ll_request_response__set_word(resp_p, 0, length);
1167 cy_as_ll_request_response__pack(resp_p, 1, length, data);
1168
1169 return cy_as_send_one(dev_p, resp_p);
1170}
1171
1172static cy_bool
1173cy_as_ll_is_e_p_transfer_related_request(cy_as_ll_request_response *rqt_p,
1174 cy_as_end_point_number_t ep)
1175{
1176 uint16_t v;
1177 uint8_t type = cy_as_ll_request_response__get_code(rqt_p);
1178
1179 if (cy_as_ll_request_response__get_context(rqt_p) !=
1180 CY_RQT_USB_RQT_CONTEXT)
1181 return cy_false;
1182
1183
1184
1185
1186
1187 if ((ep == 0) && (type == CY_RQT_ACK_SETUP_PACKET))
1188 return cy_true;
1189
1190 if (type != CY_RQT_USB_EP_DATA)
1191 return cy_false;
1192
1193 v = cy_as_ll_request_response__get_word(rqt_p, 0);
1194 if ((cy_as_end_point_number_t)((v >> 13) & 1) != ep)
1195 return cy_false;
1196
1197 return cy_true;
1198}
1199
1200cy_as_return_status_t
1201cy_as_ll_remove_ep_data_requests(cy_as_device *dev_p,
1202 cy_as_end_point_number_t ep)
1203{
1204 cy_as_context *ctxt_p;
1205 cy_as_ll_request_list_node *node_p;
1206 uint32_t imask;
1207
1208
1209
1210
1211 ctxt_p = dev_p->context[CY_RQT_USB_RQT_CONTEXT];
1212 if (ctxt_p) {
1213 for (node_p = ctxt_p->request_queue_p; node_p;
1214 node_p = node_p->next) {
1215 if (cy_as_ll_is_e_p_transfer_related_request
1216 (node_p->rqt, ep)) {
1217 cy_as_ll_remove_request(dev_p, ctxt_p,
1218 node_p->rqt, cy_false);
1219 break;
1220 }
1221 }
1222
1223
1224
1225
1226 imask = cy_as_hal_disable_interrupts();
1227
1228 if (ctxt_p->request_queue_p != 0 &&
1229 cy_as_ll_is_e_p_transfer_related_request
1230 (ctxt_p->request_queue_p->rqt, ep) &&
1231 cy_as_request_get_node_state(ctxt_p->request_queue_p) ==
1232 CY_AS_REQUEST_LIST_STATE_WAITING) {
1233 cy_as_hal_print_message("need to remove an in-transit "
1234 "request to antioch\n");
1235
1236
1237
1238
1239
1240
1241
1242 if (dev_p->ll_sending_rqt)
1243 dev_p->ll_abort_curr_rqt = cy_true;
1244 else {
1245 uint32_t state;
1246
1247 node_p = ctxt_p->request_queue_p;
1248 if (node_p->callback)
1249 node_p->callback(dev_p, ctxt_p->number,
1250 node_p->rqt, node_p->resp,
1251 CY_AS_ERROR_CANCELED);
1252
1253 ctxt_p->request_queue_p = node_p->next;
1254 state = cy_as_hal_disable_interrupts();
1255 cy_as_hal_c_b_free(node_p);
1256 cy_as_hal_enable_interrupts(state);
1257 }
1258 }
1259
1260 cy_as_hal_enable_interrupts(imask);
1261 }
1262
1263 return CY_AS_ERROR_SUCCESS;
1264}
1265