RTEMS CAN/CAN FD Stack
Loading...
Searching...
No Matches
can-queue.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0 OR GPL-2.0-or-later */
2
13/*
14 * Copyright (C) 2023-2024 Michal Lenc <michallenc@seznam.cz>
15 * Implementation is based on original LinCAN - Linux CAN bus driver
16 * Part of OrtCAN project https://ortcan.sourceforge.net/
17 * Copyright (C) 2002-2009 DCE FEE CTU Prague <http://control.fel.cvut.cz>
18 * Copyright (C) 2002-2024 Pavel Pisa <pisa@cmp.felk.cvut.cz>
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42#ifndef __DEV_CAN_CAN_QUEUE_H
43#define __DEV_CAN_CAN_QUEUE_H
44
45#include <stdatomic.h>
46#include <inttypes.h>
47#include <sys/queue.h>
48#include <rtems.h>
49#include <rtems/timespec.h>
50#include <rtems/status-checks.h>
51#include <rtems/thread.h>
52
53#include <dev/can/can-frame.h>
54#include <dev/can/can-filter.h>
55
68 atomic_uint slot_flags;
74};
75
79#define RTEMS_CAN_SLOTF_CMD ( 0x00ff )
83#define RTEMS_CAN_QUEUE_PRIO_NR ( 3 )
84
102 atomic_uint fifo_flags;
106 unsigned int out_taken;
110 unsigned long error_code;
142 rtems_mutex fifo_lock;
143};
144
145#define CAN_FIFOF_DESTROY ( 1 << 15 )
146#define CAN_FIFOF_ERROR ( 1 << 14 )
147#define CAN_FIFOF_ERR2BLOCK ( 1 << 13 )
148#define CAN_FIFOF_BLOCK ( 1 << 12 )
149#define CAN_FIFOF_OVERRUN ( 1 << 11 )
150#define CAN_FIFOF_FULL ( 1 << 10 )
151#define CAN_FIFOF_EMPTY ( 1 << 9 )
152#define CAN_FIFOF_DEAD ( 1 << 8 )
153#define CAN_FIFOF_INACTIVE ( 1 << 7 )
154#define CAN_FIFOF_FREEONEMPTY ( 1 << 6 )
155#define CAN_FIFOF_READY ( 1 << 5 )
156#define CAN_FIFOF_NOTIFYPEND ( 1 << 4 )
157#define CAN_FIFOF_RTL_MEM ( 1 << 3 )
158
169static inline int canque_fifo_test_fl( struct canque_fifo_t *fifo, int flag )
170{
171 return ( atomic_load( &fifo->fifo_flags ) &flag ) ? 1 : 0;
172}
173
183static inline void canque_fifo_set_fl( struct canque_fifo_t *fifo, int flag )
184{
185 atomic_fetch_or( &fifo->fifo_flags, flag );
186}
187
197static inline void canque_fifo_clear_fl( struct canque_fifo_t *fifo, int flag )
198{
199 atomic_fetch_and( &fifo->fifo_flags, ~flag );
200}
201
212static inline int canque_fifo_test_and_set_fl(
213 struct canque_fifo_t *fifo,
214 int flag
215)
216{
217 return ( atomic_fetch_or( &fifo->fifo_flags, flag ) & flag ) ? 1 : 0;
218}
219
230static inline int canque_fifo_test_and_clear_fl(
231 struct canque_fifo_t *fifo,
232 int flag
233)
234{
235 return ( atomic_fetch_and( &fifo->fifo_flags, ~flag ) & flag ) ? 1 : 0;
236}
237
247static inline int canque_fifo_out_is_ready_unprotected(
248 struct canque_fifo_t *fifo
249)
250{
251 return ( ( fifo->head ) != NULL ) ? 1 : 0;
252}
253
268static inline bool canque_filter_match(
269 struct can_filter *filter,
270 uint32_t id,
271 uint32_t flags )
272{
273 return ( ( filter->id^id ) & filter->id_mask ) ||
274 ( ( filter->flags^flags ) & filter->flags_mask ) ? false : true;
275}
276
288static inline int canque_fifo_get_inslot(
289 struct canque_fifo_t *fifo,
290 struct canque_slot_t **slotp,
291 int cmd
292)
293{
294 struct canque_slot_t *slot;
295 rtems_mutex_lock( &fifo->fifo_lock );
296
297 /* Get the first free slot slot from flist */
298 if ( ( slot = fifo->flist ) == NULL ) {
299 canque_fifo_set_fl( fifo, CAN_FIFOF_OVERRUN );
300 canque_fifo_set_fl( fifo, CAN_FIFOF_FULL );
301 rtems_mutex_unlock( &fifo->fifo_lock );
302 *slotp = NULL;
303 return -1;
304 }
305
306 /* Adjust free slot list */
307 if ( ( fifo->flist = slot->next ) == NULL ) {
308 canque_fifo_set_fl( fifo, CAN_FIFOF_FULL );
309 }
310
311 rtems_mutex_unlock( &fifo->fifo_lock );
312 *slotp = slot;
313 slot->slot_flags = cmd & RTEMS_CAN_SLOTF_CMD;
314
315 return 1;
316}
317
330static inline int canque_fifo_put_inslot(
331 struct canque_fifo_t *fifo,
332 struct canque_slot_t *slot
333)
334{
335 int ret = 0;
336
337 slot->next = NULL;
338 rtems_mutex_lock( &fifo->fifo_lock );
339 *fifo->tail = slot;
340 fifo->tail = &slot->next;
341
342 if ( canque_fifo_test_and_clear_fl( fifo, CAN_FIFOF_EMPTY ) ) {
343 /* Fifo has been empty before put */
344 ret = CAN_FIFOF_EMPTY;
345 }
346
347 if ( canque_fifo_test_and_clear_fl( fifo, CAN_FIFOF_INACTIVE ) ) {
348 /* Fifo has been empty before put */
349 ret |= CAN_FIFOF_INACTIVE;
350 }
351
352 if ( canque_fifo_test_and_clear_fl( fifo, CAN_FIFOF_OVERRUN ) ) {
353 /* RX overflow occured, report it with frame flag */
355 }
356
357 rtems_mutex_unlock( &fifo->fifo_lock );
358
359 return ret;
360}
361
372static inline int canque_fifo_abort_inslot(
373 struct canque_fifo_t *fifo,
374 struct canque_slot_t *slot
375)
376{
377 int ret = 0;
378
379 rtems_mutex_lock( &fifo->fifo_lock );
380 slot->next = fifo->flist;
381 fifo->flist = slot;
382 if ( canque_fifo_test_and_clear_fl( fifo, CAN_FIFOF_FULL ) ) {
383 ret = CAN_FIFOF_FULL;
384 }
385
386 rtems_mutex_unlock( &fifo->fifo_lock );
387
388 return ret;
389}
390
405static inline int canque_fifo_test_outslot(
406 struct canque_fifo_t *fifo,
407 struct canque_slot_t **slotp
408)
409{
410 int cmd;
411 struct canque_slot_t *slot;
412
413 rtems_mutex_lock( &fifo->fifo_lock );
414 if ( ( slot = fifo->head ) == NULL ) {
415 rtems_mutex_unlock( &fifo->fifo_lock );
416 *slotp = NULL;
417 return -1;
418 }
419
420 if ( ( fifo->head=slot->next ) == NULL ) {
421 fifo->tail = &fifo->head;
422 }
423
424 fifo->out_taken += 1;
425
426 rtems_mutex_unlock( &fifo->fifo_lock );
427
428 *slotp = slot;
429 cmd = slot->slot_flags;
430
431 return ( cmd & RTEMS_CAN_SLOTF_CMD );
432}
433
447static inline int canque_fifo_free_outslot(
448 struct canque_fifo_t *fifo,
449 struct canque_slot_t *slot
450)
451{
452 int ret = 0;
453
454 rtems_mutex_lock( &fifo->fifo_lock );
455 slot->next = fifo->flist;
456 fifo->flist = slot;
457 if ( canque_fifo_test_and_clear_fl( fifo, CAN_FIFOF_FULL ) ) {
458 ret = CAN_FIFOF_FULL;
459 }
460
461 fifo->out_taken -= 1;
462
463 if ( ( fifo->head ) == NULL ) {
464 canque_fifo_set_fl( fifo, CAN_FIFOF_INACTIVE );
465 ret |= CAN_FIFOF_INACTIVE;
466 if ( fifo->out_taken == 0 ) {
467 canque_fifo_set_fl( fifo, CAN_FIFOF_EMPTY );
468 ret |= CAN_FIFOF_EMPTY;
469 }
470 }
471
472 rtems_mutex_unlock( &fifo->fifo_lock );
473
474 return ret;
475}
476
488static inline int canque_fifo_again_outslot(
489 struct canque_fifo_t *fifo,
490 struct canque_slot_t *slot
491)
492{
493 int ret = 0;
494
495 rtems_mutex_lock( &fifo->fifo_lock );
496 if ( ( slot->next = fifo->head ) == NULL ) {
497 fifo->tail = &slot->next;
498 ret = CAN_FIFOF_INACTIVE;
499 }
500
501 fifo->out_taken -= 1;
502
503 fifo->head = slot;
504 rtems_mutex_unlock( &fifo->fifo_lock );
505
506 return ret;
507}
508
517static inline int canque_fifo_slot_size( int maxdlen )
518{
519 return offsetof( struct canque_slot_t, frame.data ) + maxdlen +
520 ( ( RTEMS_ALIGNOF(struct canque_slot_t) - 1 ) &
521 ~( RTEMS_ALIGNOF(struct canque_slot_t) - 1 ) );
522}
523
524int canque_fifo_flush_slots( struct canque_fifo_t *fifo );
525
526int canque_fifo_init_slots( struct canque_fifo_t *fifo );
527
528struct canque_edge_t;
529TAILQ_HEAD( canqueue_edges_list_t, canque_edge_t );
530
567 struct canqueue_edges_list_t *peershead;
582 atomic_uint edge_used;
593};
594
595struct canque_ends_t;
596TAILQ_HEAD( canqueue_ends_list_t, canque_ends_t );
597
608 struct canqueue_edges_list_t active[RTEMS_CAN_QUEUE_PRIO_NR];
613 struct canqueue_edges_list_t idle;
617 struct canqueue_edges_list_t inlist;
622 struct canqueue_edges_list_t outlist;
627 rtems_mutex ends_lock;
647 void (*notify)( struct canque_ends_t *qends, struct canque_edge_t *qedge,
648 int what );
654};
655
659#define CANQUEUE_NOTIFY_EMPTY ( 1 )
663#define CANQUEUE_NOTIFY_SPACE ( 2 )
667#define CANQUEUE_NOTIFY_PROC ( 3 )
672#define CANQUEUE_NOTIFY_NOUSR ( 4 )
676#define CANQUEUE_NOTIFY_DEAD ( 5 )
680#define CANQUEUE_NOTIFY_DEAD_WANTED ( 6 )
684#define CANQUEUE_NOTIFY_ATTACH ( 7 )
685
696static inline void canque_notify_inends( struct canque_edge_t *qedge, int what )
697{
698 if ( qedge->inends ) {
699 if ( qedge->inends->notify ) {
700 qedge->inends->notify( qedge->inends, qedge,what );
701 }
702 }
703}
704
715static inline void canque_notify_outends(
716 struct canque_edge_t *qedge,
717 int what
718)
719{
720 if ( qedge->outends ) {
721 if ( qedge->outends->notify ) {
722 qedge->outends->notify( qedge->outends, qedge, what );
723 }
724 }
725}
726
736static inline void canque_notify_bothends(
737 struct canque_edge_t *qedge,
738 int what
739)
740{
741 canque_notify_inends( qedge, what );
742 canque_notify_outends( qedge, what );
743}
744
758static inline void canque_activate_edge(
759 struct canque_ends_t *inends,
760 struct canque_edge_t *qedge
761)
762{
763 struct canque_ends_t *outends;
764
765 if ( qedge->edge_prio >= RTEMS_CAN_QUEUE_PRIO_NR ) {
767 }
768
769 if ( ( outends = qedge->outends ) != NULL ) {
770 rtems_mutex_lock( &outends->ends_lock );
771 rtems_mutex_lock( &qedge->fifo.fifo_lock );
772 if ( qedge->peershead != &outends->active[qedge->edge_prio] ) {
773 if ( qedge->peershead != NULL ) {
774 TAILQ_REMOVE( qedge->peershead, qedge, activepeers );
775 }
776
777 TAILQ_INSERT_HEAD( &outends->active[qedge->edge_prio], qedge, activepeers );
778 qedge->peershead = &outends->active[qedge->edge_prio];
779 }
780 rtems_mutex_unlock( &qedge->fifo.fifo_lock );
781 rtems_mutex_unlock( &outends->ends_lock );
782 }
783}
784
785static inline void canque_edge_to_idle_unprotected(
786 struct canque_ends_t *outends,
787 struct canque_edge_t *qedge
788)
789{
790 if ( qedge->peershead != NULL ) {
791 TAILQ_REMOVE( qedge->peershead, qedge, activepeers );
792 }
793 TAILQ_INSERT_TAIL( &outends->idle, qedge, activepeers );
794 qedge->peershead = &outends->idle;
795}
796
798 struct canque_ends_t *qends,
799 struct canque_edge_t **qedgep,
800 struct canque_slot_t **slotp,
801 int cmd
802);
803
805 struct canque_ends_t *qends,
806 struct canque_edge_t **qedgep,
807 struct canque_slot_t **slotp,
808 const struct can_frame_header *header,
809 int cmd,
810 int prio
811);
812
813int canque_test_inslot( struct canque_ends_t *qends );
814
816 struct canque_ends_t *qends,
817 struct canque_edge_t *qedge,
818 struct canque_slot_t *slot
819);
820
822 struct canque_ends_t *qends,
823 struct canque_edge_t *qedge,
824 struct canque_slot_t *slot
825);
826
828 struct canque_ends_t *qends,
829 struct canque_edge_t *src_edge,
830 struct can_frame *frame,
831 unsigned int flags2add
832);
833
835 struct canque_ends_t *qends,
836 struct canque_edge_t **qedgep,
837 struct canque_slot_t **slotp
838);
839
841 struct canque_ends_t *qends,
842 int prio_min
843);
844
846 struct canque_ends_t *qends,
847 struct canque_edge_t *qedge,
848 struct canque_slot_t *slot
849);
850
852 struct canque_ends_t *qends,
853 struct canque_edge_t *qedge,
854 struct canque_slot_t *slot
855);
856
857int canque_flush( struct canque_edge_t *qedge );
858
859int canqueue_disconnect_edge( struct canque_edge_t *qedge );
860
862 struct canque_edge_t *qedge,
863 struct canque_ends_t *inends,
864 struct canque_ends_t *outends
865);
866
867int canqueue_ends_init_gen( struct canque_ends_t *qends );
868
869void canqueue_block_inlist( struct canque_ends_t *qends );
870
871void canqueue_block_outlist( struct canque_ends_t *qends );
872
873int canqueue_ends_kill_inlist( struct canque_ends_t *qends, int send_rest );
874
875int canqueue_ends_kill_outlist( struct canque_ends_t *qends );
876
877int canqueue_ends_flush_inlist( struct canque_ends_t *qends );
878
879int canqueue_ends_flush_outlist( struct canque_ends_t *qends );
880
881/* edge reference and traversal functions */
882
883void canque_edge_do_dead( struct canque_edge_t *edge );
884
893static inline void canque_edge_incref( struct canque_edge_t *edge )
894{
895 atomic_fetch_add( &edge->edge_used, 1 );
896}
897
898/* Non-inlined version of edge reference decrement */
899void __canque_edge_decref( struct canque_edge_t *edge );
900
901static inline void __canque_edge_decref_body( struct canque_edge_t *edge )
902{
903 int dead_fl = 0;
904 struct canque_ends_t *inends=edge->inends;
905 struct canque_ends_t *outends=edge->outends;
906
907 if ( inends < outends ) {
908 rtems_mutex_lock( &inends->ends_lock );
909 rtems_mutex_lock( &outends->ends_lock );
910 if ( atomic_fetch_sub( &edge->edge_used, 1 ) == 1 ) {
911 dead_fl = !canque_fifo_test_and_set_fl( &edge->fifo, CAN_FIFOF_DEAD );
912 }
913 rtems_mutex_unlock( &outends->ends_lock );
914 rtems_mutex_unlock( &inends->ends_lock );
915 } else {
916 rtems_mutex_lock( &outends->ends_lock );
917 if ( outends != inends ) {
918 rtems_mutex_lock( &inends->ends_lock );
919 }
920 if ( atomic_fetch_sub( &edge->edge_used, 1 ) == 1 ) {
921 dead_fl = !canque_fifo_test_and_set_fl( &edge->fifo, CAN_FIFOF_DEAD );
922 }
923 if ( outends != inends ) {
924 rtems_mutex_unlock( &inends->ends_lock );
925 }
926 rtems_mutex_unlock( &outends->ends_lock );
927 }
928
929 if ( dead_fl ) {
930 canque_edge_do_dead( edge );
931 }
932}
933
946static inline void canque_edge_decref( struct canque_edge_t *edge )
947{
948 unsigned int x;
949
950 x = atomic_load_explicit( &edge->edge_used, memory_order_relaxed );
951
952 do {
953 if ( x <= 1 ) {
954 return __canque_edge_decref( edge );
955 }
956 } while( !atomic_compare_exchange_strong(&edge->edge_used, &x, x-1 ) );
957}
958
959static inline struct canque_edge_t *canque_first_inedge(
960 struct canque_ends_t *qends
961)
962{
963 struct canque_edge_t *edge;
964
965 rtems_mutex_lock( &qends->ends_lock );
966 edge = TAILQ_FIRST( &qends->inlist );
967
968skip_dead:
969 if ( edge != NULL ) {
970 if ( canque_fifo_test_fl( &edge->fifo, CAN_FIFOF_DEAD ) ) {
971 edge = TAILQ_NEXT( edge, inpeers );
972 goto skip_dead;
973 }
974 canque_edge_incref( edge );
975 } else {
976 edge = NULL;
977 }
978 rtems_mutex_unlock( &qends->ends_lock );
979 return edge;
980}
981
982
983static inline struct canque_edge_t *canque_next_inedge(
984 struct canque_ends_t *qends,
985 struct canque_edge_t *edge
986)
987{
988 struct canque_edge_t *next;
989
990 rtems_mutex_lock( &qends->ends_lock );
991 next = TAILQ_NEXT( edge, inpeers );
992
993skip_dead:
994 if ( next != NULL ) {
995 if ( canque_fifo_test_fl( &edge->fifo,CAN_FIFOF_DEAD ) ) {
996 next = TAILQ_NEXT( next, inpeers );
997 goto skip_dead;
998 }
999 canque_edge_incref( next );
1000 } else {
1001 next = NULL;
1002 }
1003 rtems_mutex_unlock( &qends->ends_lock );
1004 canque_edge_decref( edge );
1005 return next;
1006}
1007
1008#define canque_for_each_inedge( qends, edge ) \
1009 for ( edge = canque_first_inedge( qends ); edge; edge = canque_next_inedge( qends, edge ) )
1010
1011static inline
1012struct canque_edge_t *canque_first_outedge( struct canque_ends_t *qends )
1013{
1014 struct canque_edge_t *edge;
1015
1016 rtems_mutex_lock( &qends->ends_lock );
1017 edge = TAILQ_FIRST( &qends->outlist );
1018
1019skip_dead:
1020 if ( edge != NULL ) {
1021 if ( canque_fifo_test_fl( &edge->fifo, CAN_FIFOF_DEAD ) ) {
1022 edge = TAILQ_NEXT( edge, outpeers );
1023 goto skip_dead;
1024 }
1025 canque_edge_incref( edge );
1026 } else {
1027 edge = NULL;
1028 }
1029 rtems_mutex_unlock( &qends->ends_lock );
1030 return edge;
1031}
1032
1033
1034static inline
1035struct canque_edge_t *canque_next_outedge(
1036 struct canque_ends_t *qends,
1037 struct canque_edge_t *edge
1038)
1039{
1040 struct canque_edge_t *next;
1041
1042 rtems_mutex_lock( &qends->ends_lock );
1043 next = TAILQ_NEXT( edge, outpeers );
1044
1045skip_dead:
1046 if ( next != NULL ) {
1047 if ( canque_fifo_test_fl( &edge->fifo,CAN_FIFOF_DEAD ) ) {
1048 next = TAILQ_NEXT( next, outpeers );
1049 goto skip_dead;
1050 }
1051 canque_edge_incref( next );
1052 } else {
1053 next = NULL;
1054 }
1055 rtems_mutex_unlock( &qends->ends_lock );
1056 canque_edge_decref( edge );
1057 return next;
1058}
1059
1060#define canque_for_each_outedge( qends, edge ) \
1061 for ( edge = canque_first_outedge( qends ); edge; edge = canque_next_outedge( qends, edge ) )
1062
1063/* Linux kernel specific functions */
1064
1066 struct canque_fifo_t *fifo,
1067 int slotsnr,
1068 int maxdlen
1069);
1070
1072
1073struct canque_edge_t *canque_new_edge_kern( int slotsnrm, int maxdlen );
1074
1076 struct canque_ends_t *qends,
1077 struct timespec *ts
1078);
1079
1081 struct canque_ends_t *qends,
1082 struct canque_edge_t *qedge,
1083 bool nowait,
1084 rtems_interval timeout
1085);
1086
1087int canqueue_ends_dispose_kern( struct canque_ends_t *qends, bool nonblock );
1088int canqueue_kern_initialize( void );
1089
1090#endif /*_CAN_QUEUE_H*/
This header file is part of CAN/CAN FD bus common support. It implements structure that represents fi...
This header file is part of CAN/CAN FD bus common support. It implements CAN frame structure and rela...
#define RTEMS_CAN_SLOTF_CMD
Macro for command associated with allocated slot.
Definition: can-queue.h:79
int canque_pending_outslot_prio(struct canque_ends_t *qends, int prio_min)
This function tests ready outslot with minimum priority.
Definition: can-queue.c:533
void canqueue_block_inlist(struct canque_ends_t *qends)
This function blocks slot allocation of all outgoing edges of specified ends.
Definition: can-queue.c:861
int canque_put_inslot(struct canque_ends_t *qends, struct canque_edge_t *qedge, struct canque_slot_t *slot)
This function schedules filled slot for processing.
Definition: can-queue.c:295
int canque_flush(struct canque_edge_t *qedge)
This function flushes all ready slots in the edge.
Definition: can-queue.c:669
int canque_fifo_init_slots(struct canque_fifo_t *fifo)
This function initializes slot chain of one CAN FIFO.
Definition: can-queue.c:100
int canqueue_disconnect_edge(struct canque_edge_t *qedge)
This function disconnects edge from communication entities.
Definition: can-queue.c:782
int canque_fifo_done_kern(struct canque_fifo_t *fifo)
This function frees slots allocated for CAN FIFO.
Definition: can-quekern.c:332
int canque_abort_inslot(struct canque_ends_t *qends, struct canque_edge_t *qedge, struct canque_slot_t *slot)
This function aborts preparation of the message in the slot.
Definition: can-queue.c:329
int canque_get_inslot(struct canque_ends_t *qends, struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd)
This function finds one outgoing edge and allocates slot from it.
Definition: can-queue.c:143
int canque_fifo_flush_slots(struct canque_fifo_t *fifo)
This function frees all ready slots from the FIFO.
Definition: can-queue.c:60
int canque_filter_frame2edges(struct canque_ends_t *qends, struct canque_edge_t *src_edge, struct can_frame *frame, unsigned int flags2add)
This function sends message into all edges which accept its ID.
Definition: can-queue.c:362
int canque_test_inslot(struct canque_ends_t *qends)
This function tests whether there is a free space in any outgoing edge.
Definition: can-queue.c:261
int canque_test_outslot(struct canque_ends_t *qends, struct canque_edge_t **qedgep, struct canque_slot_t **slotp)
This function tests and retrieves ready slot for given ends.
Definition: can-queue.c:456
int canqueue_ends_init_gen(struct canque_ends_t *qends)
This function implements subsystem independent routine to initialize ends state.
Definition: can-queue.c:700
int canque_get_inslot4prio(struct canque_ends_t *qends, struct canque_edge_t **qedgep, struct canque_slot_t **slotp, const struct can_frame_header *header, int cmd, int prio)
This function finds best outgoing edge and slot for given ID.
Definition: can-queue.c:192
int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge, bool nowait, rtems_interval timeout)
This function waits for all slots processing.
Definition: can-quekern.c:247
int canqueue_ends_kill_outlist(struct canque_ends_t *qends)
This function sends request to die to all incomming edges.
Definition: can-queue.c:931
void canqueue_block_outlist(struct canque_ends_t *qends)
This function blocks slot allocation of all incoming edges of specified ends.
Definition: can-queue.c:879
int canque_free_outslot(struct canque_ends_t *qends, struct canque_edge_t *qedge, struct canque_slot_t *slot)
This function frees processed output slot.
Definition: can-queue.c:583
#define RTEMS_CAN_QUEUE_PRIO_NR
This macro contains maximum number of priorites for queues.
Definition: can-queue.h:83
int canqueue_ends_dispose_kern(struct canque_ends_t *qends, bool nonblock)
This function provides finalizing of the ends structure for clients.
Definition: can-quekern.c:451
int canqueue_ends_flush_inlist(struct canque_ends_t *qends)
Definition: can-queue.c:949
struct canque_edge_t * canque_new_edge_kern(int slotsnrm, int maxdlen)
This function allocates new edge structure.
Definition: can-quekern.c:352
int canqueue_kern_initialize(void)
This function provides initialization of kernel queue side.
Definition: can-quekern.c:486
int canqueue_ends_flush_outlist(struct canque_ends_t *qends)
This function flushes all messages in outgoing edges.
Definition: can-queue.c:967
int canque_fifo_init_kern(struct canque_fifo_t *fifo, int slotsnr, int maxdlen)
This function initializes one CAN FIFO.
Definition: can-quekern.c:298
int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends)
This function connects edge between two communication entities.
Definition: can-queue.c:724
int canque_again_outslot(struct canque_ends_t *qends, struct canque_edge_t *qedge, struct canque_slot_t *slot)
This function reschedules output slot to process it again later.
Definition: can-queue.c:628
int canqueue_ends_sync_all_kern(struct canque_ends_t *qends, struct timespec *ts)
This function waits for all ends to TX their messages.
Definition: can-quekern.c:391
int canqueue_ends_kill_inlist(struct canque_ends_t *qends, int send_rest)
This function sends request to die to all outgoing edges.
Definition: can-queue.c:899
#define CAN_FRAME_FIFO_OVERFLOW
Represents local FIFO overflow.
Definition: can-frame.h:116
This structure is used to represent CAN ID and flags in one unified structure.
Definition: can-filter.h:49
uint32_t flags_mask
This member is a bitfield that holds CAN flags forbidden in CAN frame. If the frame has some of these...
Definition: can-filter.h:75
uint32_t flags
This member is a bitfield that holds CAN flags required in CAN frame to be assigned to the FIFO queue...
Definition: can-filter.h:67
uint32_t id
This member is a bitfield that holds required CAN identifier values to assign CAN frame to the FIFO q...
Definition: can-filter.h:54
uint32_t id_mask
This member is a bitfield that holds forbidden CAN identifier values. If the frame has identifier in ...
Definition: can-filter.h:60
This structure represents the CAN message header.
Definition: can-frame.h:505
uint16_t flags
This member holds the CAN flags. These are used to pass additional information between driver and app...
Definition: can-frame.h:521
This structure represents one CAN frame. It consists of CAN header and data.
Definition: can-frame.h:533
struct can_frame_header header
This member stores the structure can_frame_header representing CAN header.
Definition: can-frame.h:538
uint8_t data[CAN_FRAME_MAX_DLEN]
This member stores CAN data.
Definition: can-frame.h:542
This structure represents one direction connection from messages source ( inends) to message consumer...
Definition: can-queue.h:537
struct can_filter filter
This member holds place where primitive can_filter is located.
Definition: can-queue.h:547
atomic_uint edge_used
This member holds the atomic usage counter, mainly used for safe destruction of the edge.
Definition: can-queue.h:582
TAILQ_ENTRY(canque_edge_t) activepeers
This member holds the lists of peers FIFOs connected by their output side ( outends) to the same term...
struct canqueue_edges_list_t * peershead
This member holds the pointer to the activepeers head.
Definition: can-queue.h:567
int edge_prio
This member holds the the assigned queue priority from the range 0 to RTEMS_CAN_QUEUE_PRIO_NR - 1.
Definition: can-queue.h:587
TAILQ_ENTRY(canque_edge_t) inpeers
This member holds the lists of all peers FIFOs connected by their input side ( inends) to the same te...
struct canque_fifo_t fifo
This member holds place where primitive canque_fifo_t FIFO is located.
Definition: can-queue.h:542
int edge_num
This member holds the edge sequential number intended for debugging purposes only.
Definition: can-queue.h:592
TAILQ_ENTRY(canque_edge_t) outpeers
This member holds the lists of all peers FIFOs connected by their output side ( outends) to the same ...
struct canque_ends_t * inends
This member holds the pointer to the FIFO input side terminal ( canque_ends_t).
Definition: can-queue.h:572
struct canque_ends_t * outends
This member holds the pointer to the FIFO output side terminal ( canque_ends_t).
Definition: can-queue.h:577
This structure represents place to connect edges to for CAN communication entity. The zero,...
Definition: can-queue.h:603
TAILQ_ENTRY(canque_ends_t) dead_peers
This member is used to chain ends wanting for postponed destruction.
struct canqueue_edges_list_t active[RTEMS_CAN_QUEUE_PRIO_NR]
This member holds the array of the lists of active edges directed to the ends structure.
Definition: can-queue.h:608
void(* notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what)
pointer to notify procedure. The next state changes are notified.
Definition: can-queue.h:647
struct canqueue_edges_list_t idle
This member holds the list of the edges directed to the ends structure with empty FIFOs.
Definition: can-queue.h:613
rtems_mutex ends_lock
This member holds the lock synchronizing operations between threads accessing the ends.
Definition: can-queue.h:627
struct canqueue_edges_list_t outlist
This member holds the list of all incoming edges output sides. Each of there edges is listed on one o...
Definition: can-queue.h:622
struct canqueue_edges_list_t inlist
This member holds the list of outgoing edges input sides.
Definition: can-queue.h:617
This structure represents CAN FIFO queue. It is implemented as a single linked list of slots prepared...
Definition: can-queue.h:91
int maxdlen
This member holds maximum data length of one CAN frame.
Definition: can-queue.h:133
atomic_uint fifo_flags
This field holds global flags describing state of the FIFO. CAN_FIFOF_ERROR is set when some error co...
Definition: can-queue.h:102
struct canque_slot_t * entry
This member holds the pointer to the memory allocated for the list slots.
Definition: can-queue.h:129
struct canque_slot_t * head
This member holds the pointer to the FIFO head, oldest slot.
Definition: can-queue.h:114
unsigned long error_code
This member holds futher description of error condition.
Definition: can-queue.h:110
struct canque_slot_t * flist
This member holds the pointer to list of the free slots associated with queue.
Definition: can-queue.h:124
struct canque_slot_t ** tail
This member holds the pointer to the location, where pointer to newly inserted slot should be added.
Definition: can-queue.h:119
unsigned int out_taken
This member holds the number of elements in the fifo.
Definition: can-queue.h:106
rtems_mutex fifo_lock
This member holds the lock to ensure atomicity of slot manipulation operations.
Definition: can-queue.h:142
int slotsnr
This member holds the number of allocated slots.
Definition: can-queue.h:137
This structure represents one CAN message slot in the CAN FIFO queue.
Definition: can-queue.h:59
struct can_frame frame
This member holds can_frame structure representing one CAN frame/message.
Definition: can-queue.h:73
atomic_uint slot_flags
Space for flags and optional command describing action associated with slot data.
Definition: can-queue.h:68
struct canque_slot_t * next
Pointer to next/younger slot.
Definition: can-queue.h:63