]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/include/can_queue.h
Updated "sendburst" utility to reflect enhancements in in "readburst".
[lincan.git] / lincan / include / can_queue.h
1 #ifndef _CAN_QUEUE_H
2 #define _CAN_QUEUE_H
3
4 #include <linux/version.h>
5 #include <linux/wait.h>
6 #include <linux/list.h>
7 #include <asm/io.h>
8 #include <asm/atomic.h>
9 #include "./can.h"
10 #include "./constants.h"
11
12 /* Next is not sctrictly correct, because of 2.3.0, 2.3.1, 2.3.2
13    kernels need next definitions  too */
14 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)) /* may need correction */
15   #define wait_queue_head_t struct wait_queue *
16   #define wait_queue_t      struct wait_queue
17   #define init_waitqueue_head(queue_head) (*queue_head=NULL)
18   #define init_waitqueue_entry(qentry,qtask) \
19                         (qentry->next=NULL,qentry->task=qtask)
20   #define DECLARE_WAIT_QUEUE_HEAD(name) \
21         struct wait_queue * name=NULL
22   #define DECLARE_WAITQUEUE(wait, current) \
23         struct wait_queue wait = { current, NULL }
24   #define init_MUTEX(sem) (*sem=MUTEX)
25   #define DECLARE_MUTEX(name) struct semaphore name=MUTEX
26 #endif /* 2.2.19 */
27
28
29 /**
30  * struct canque_slot_t - one CAN message slot in the CAN FIFO queue 
31  * @next: pointer to the next/younger slot
32  * @slot_flags: space for flags and optional command describing action
33  *      associated with slot data
34  * @msg: space for one CAN message
35  *
36  * This structure is used to store CAN messages in the CAN FIFO queue.
37  */
38  struct canque_slot_t {
39         struct canque_slot_t *next;
40         unsigned long slot_flags;
41         struct canmsg_t msg;
42 };
43
44 #define CAN_SLOTF_CMD   0x00ff  /*  */
45
46 /**
47  * struct canque_fifo_t - CAN FIFO queue representation
48  * @fifo_flags: this field holds global flags describing state of the FIFO.
49  *      %CAN_FIFOF_ERROR is set when some error condition occurs.
50  *      %CAN_FIFOF_ERR2BLOCK defines, that error should lead to the FIFO block state.
51  *      %CAN_FIFOF_BLOCK state blocks insertion of the next messages. 
52  *      %CAN_FIFOF_OVERRUN attempt to acquire new slot, when FIFO is full. 
53  *      %CAN_FIFOF_FULL indicates FIFO full state. 
54  *      %CAN_FIFOF_EMPTY indicates no allocated slot in the FIFO.
55  *      %CAN_FIFOF_DEAD condition indication. Used when FIFO is beeing destroyed.
56  * @error_code: futher description of error condition
57  * @head: pointer to the FIFO head, oldest slot
58  * @tail: pointer to the location, where pointer to newly inserted slot
59  *      should be added
60  * @flist: pointer to list of the free slots associated with queue
61  * @entry: pointer to the memory allocated for the list slots.
62  * @fifo_lock: the lock to ensure atomicity of slot manipulation operations.
63  *
64  * This structure represents CAN FIFO queue. It is implemented as 
65  * a single linked list of slots prepared for processing. The empty slots
66  * are stored in single linked list (@flist).
67  */
68 struct canque_fifo_t {
69         unsigned long fifo_flags;
70         unsigned long error_code;
71         struct canque_slot_t *head;     /* points to the oldest entry */
72         struct canque_slot_t **tail;    /* points to NULL pointer for chaining */
73         struct canque_slot_t *flist;    /* points the first entry in the free list */
74         struct canque_slot_t *entry;    /* points to first allocated entry */
75         spinlock_t fifo_lock;   /* spin_lock_irqsave / spin_lock_irqrestore */
76 };
77
78 #define CAN_FIFOF_DESTROY_b     15
79 #define CAN_FIFOF_ERROR_b       14
80 #define CAN_FIFOF_ERR2BLOCK_b   13
81 #define CAN_FIFOF_BLOCK_b       12
82 #define CAN_FIFOF_OVERRUN_b     11
83 #define CAN_FIFOF_FULL_b        10
84 #define CAN_FIFOF_EMPTY_b       9
85 #define CAN_FIFOF_DEAD_b        8
86
87 #define CAN_FIFOF_DESTROY       (1<<CAN_FIFOF_DESTROY_b)
88 #define CAN_FIFOF_ERROR         (1<<CAN_FIFOF_ERROR_b)
89 #define CAN_FIFOF_ERR2BLOCK     (1<<CAN_FIFOF_ERR2BLOCK_b)
90 #define CAN_FIFOF_BLOCK         (1<<CAN_FIFOF_BLOCK_b)
91 #define CAN_FIFOF_OVERRUN       (1<<CAN_FIFOF_OVERRUN_b)
92 #define CAN_FIFOF_FULL          (1<<CAN_FIFOF_FULL_b)
93 #define CAN_FIFOF_EMPTY         (1<<CAN_FIFOF_EMPTY_b)
94 #define CAN_FIFOF_DEAD          (1<<CAN_FIFOF_DEAD_b)
95
96 #define canque_fifo_test_fl(fifo,fifo_fl) \
97   test_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
98 #define canque_fifo_set_fl(fifo,fifo_fl) \
99   set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
100 #define canque_fifo_clear_fl(fifo,fifo_fl) \
101   clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
102 #define canque_fifo_test_and_set_fl(fifo,fifo_fl) \
103   test_and_set_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
104 #define canque_fifo_test_and_clear_fl(fifo,fifo_fl) \
105   test_and_clear_bit(CAN_FIFOF_##fifo_fl##_b,&(fifo)->fifo_flags)
106
107
108 /**
109  * canque_fifo_get_inslot - allocate slot for the input of one CAN message 
110  * @fifo: pointer to the FIFO structure
111  * @slotp: pointer to location to store pointer to the allocated slot.
112  * @cmd: optional command associated with allocated slot.
113  *
114  * Return Value: The function returns negative value if there is no
115  *      free slot in the FIFO queue.
116  */
117 static inline
118 int canque_fifo_get_inslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp, int cmd)
119 {
120         unsigned long flags;
121         struct canque_slot_t *slot;
122         spin_lock_irqsave(&fifo->fifo_lock, flags);
123         /* get the first free slot slot from flist */
124         if(!(slot=fifo->flist)) {
125                 canque_fifo_set_fl(fifo,OVERRUN);
126                 canque_fifo_set_fl(fifo,FULL);
127                 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
128                 *slotp=NULL;
129                 return -1;
130         }
131         /* adjust free slot list */
132         if(!(fifo->flist=slot->next))
133                 canque_fifo_set_fl(fifo,FULL);
134         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
135         *slotp=slot;
136         slot->slot_flags=cmd&CAN_SLOTF_CMD;
137         return 1;
138 }
139
140 /**
141  * canque_fifo_put_inslot - releases slot to further processing
142  * @fifo: pointer to the FIFO structure
143  * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
144  *
145  * Return Value: The nonzero return value indicates, that the queue was empty
146  *      before call to the function. The caller should wake-up output side of the queue.
147  */
148 static inline
149 int canque_fifo_put_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
150 {
151         int ret;
152         unsigned long flags;
153         slot->next=NULL;
154         spin_lock_irqsave(&fifo->fifo_lock, flags);
155         if(*fifo->tail) printk(KERN_CRIT "canque_fifo_put_inslot: fifo->tail != NULL\n");
156         *fifo->tail=slot;
157         fifo->tail=&slot->next;
158         if(canque_fifo_test_and_clear_fl(fifo,EMPTY))
159           ret=CAN_FIFOF_EMPTY;  /* Fifo has been empty before put */
160         else 
161           ret=0;
162         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
163         return ret;
164 }
165
166 /**
167  * canque_fifo_abort_inslot - release and abort slot
168  * @fifo: pointer to the FIFO structure
169  * @slot: pointer to the slot previously acquired by canque_fifo_get_inslot().
170  *
171  * Return Value: The nonzero value indicates, that fifo was full
172  */
173 static inline
174 int canque_fifo_abort_inslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
175 {
176         int ret=0;
177         unsigned long flags;
178         spin_lock_irqsave(&fifo->fifo_lock, flags);
179         slot->next=fifo->flist;
180         fifo->flist=slot;
181         if(canque_fifo_test_and_clear_fl(fifo,FULL))
182                 ret=CAN_FIFOF_FULL;
183         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
184         return ret;
185 }
186
187 /**
188  * canque_fifo_test_outslot - test and get ready slot from the FIFO
189  * @fifo: pointer to the FIFO structure
190  * @slotp: pointer to location to store pointer to the oldest slot from the FIFO.
191  *
192  * Return Value: The negative value indicates, that queue is empty.
193  *      The positive or zero value represents command stored into slot by
194  *      the call to the function canque_fifo_get_inslot().
195  *      The successfully acquired FIFO output slot has to be released by
196  *      the call canque_fifo_free_outslot() or canque_fifo_again_outslot().
197  */
198 static inline
199 int canque_fifo_test_outslot(struct canque_fifo_t *fifo, struct canque_slot_t **slotp)
200 {
201         unsigned long flags;
202         int cmd;
203         struct canque_slot_t *slot;
204         spin_lock_irqsave(&fifo->fifo_lock, flags);
205         if(!(slot=fifo->head)){;
206                 canque_fifo_set_fl(fifo,EMPTY);
207                 spin_unlock_irqrestore(&fifo->fifo_lock, flags);
208                 *slotp=NULL;
209                 return -1;
210         }
211         if(!(fifo->head=slot->next))
212                 fifo->tail=&fifo->head;
213         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
214
215         *slotp=slot;
216         cmd=slot->slot_flags;
217         return cmd&CAN_SLOTF_CMD;
218 }
219
220
221 /**
222  * canque_fifo_free_outslot - free processed FIFO slot
223  * @fifo: pointer to the FIFO structure
224  * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
225  *
226  * Return Value: The returned value informs about FIFO state change.
227  *      The mask %CAN_FIFOF_FULL indicates, that the FIFO was full before
228  *      the function call. The mask %CAN_FIFOF_EMPTY informs, that last ready slot
229  *      has been processed.
230  */
231 static inline
232 int canque_fifo_free_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
233 {
234         int ret=0;
235         unsigned long flags;
236         spin_lock_irqsave(&fifo->fifo_lock, flags);
237         slot->next=fifo->flist;
238         fifo->flist=slot;
239         if(canque_fifo_test_and_clear_fl(fifo,FULL))
240                 ret=CAN_FIFOF_FULL;
241         if(!(fifo->head)){
242                 canque_fifo_set_fl(fifo,EMPTY);
243                 ret|=CAN_FIFOF_EMPTY;
244         }
245         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
246         return ret;
247 }
248
249 /**
250  * canque_fifo_again_outslot - interrupt and postpone processing of the slot
251  * @fifo: pointer to the FIFO structure
252  * @slot: pointer to the slot previously acquired by canque_fifo_test_outslot().
253  *
254  * Return Value: The function cannot fail..
255  */
256 static inline
257 int canque_fifo_again_outslot(struct canque_fifo_t *fifo, struct canque_slot_t *slot)
258 {
259         unsigned long flags;
260         spin_lock_irqsave(&fifo->fifo_lock, flags);
261         if(!(slot->next=fifo->head))
262                 fifo->tail=&slot->next;
263         fifo->head=slot;
264         spin_unlock_irqrestore(&fifo->fifo_lock, flags);
265         return 1;
266 }
267
268 int canque_fifo_flush_slots(struct canque_fifo_t *fifo);
269
270 int canque_fifo_init_slots(struct canque_fifo_t *fifo, int slotsnr);
271
272 int canque_fifo_done(struct canque_fifo_t *fifo);
273
274 #define CANQUEUE_PRIO_NR  3
275
276 /* Forward declarations for external types */
277 struct msgobj_t;
278 struct chip_t;
279
280 /**
281  * struct canque_edge_t - CAN message delivery subsystem graph edge
282  * @fifo: place where primitive @struct canque_fifo_t FIFO is located.
283  * @filtid: the possible CAN message identifiers filter.
284  * @filtmask: the filter mask, the comparison considers only
285  *      @filtid bits corresponding to set bits in the @filtmask field.
286  * @inpeers: the lists of all peer FIFOs connected by their
287  *      input side (@inends) to the same terminal (@struct canque_ends_t).
288  * @outpeers: the lists of all peer FIFOs connected by their
289  *      output side (@outends) to the same terminal (@struct canque_ends_t).
290  * @inends: the pointer to the FIFO input side terminal (@struct canque_ends_t).
291  * @outends: the pointer to the FIFO output side terminal (@struct canque_ends_t).
292  * @edge_used: the atomic usage counter, mainly used for safe destruction of the edge.
293  * @edge_prio: the assigned queue priority from the range 0 to %CANQUEUE_PRIO_NR-1
294  * @edge_num: edge sequential number intended for debugging purposes only
295  *
296  * This structure represents one direction connection from messages source 
297  * (@inends) to message consumer (@outends) fifo ends hub. The edge contains
298  * &struct canque_fifo_t for message fifo implementation.
299  */
300 struct canque_edge_t {
301         struct canque_fifo_t fifo;
302         unsigned long filtid;
303         unsigned long filtmask;
304         struct list_head inpeers;
305         struct list_head outpeers;
306         struct canque_ends_t *inends;
307         struct canque_ends_t *outends;
308         atomic_t edge_used;
309         int edge_prio;
310         int edge_num;
311 };
312
313 /**
314  * struct canque_ends_t - CAN message delivery subsystem graph vertex (FIFO ends)
315  * @active: the array of the lists of active edges directed to the ends structure
316  *      with ready messages. The array is indexed by the edges priorities. 
317  * @idle: the list of the edges directed to the ends structure with empty FIFOs.
318  * @inlist: the list of outgoing edges input sides.
319  * @ends_lock: the lock synchronizing operations between threads accessing
320  *      same ends structure.
321  * @notify: pointer to notify procedure. The next state changes are notified.
322  *      %CANQUEUE_NOTIFY_EMPTY (out->in call) - all slots are processed by FIFO out side. 
323  *      %CANQUEUE_NOTIFY_SPACE (out->in call) - full state negated => there is space for new message.
324  *      %CANQUEUE_NOTIFY_PROC  (in->out call) - empty state negated => out side is requested to process slots.
325  *      %CANQUEUE_NOTIFY_NOUSR (both) - notify, that the last user has released the edge usage
326  *              called with some lock to prevent edge disappear.
327  *      %CANQUEUE_NOTIFY_DEAD  (both) - edge is in progress of deletion.
328  *      %CANQUEUE_NOTIFY_ATACH (both) - new edge has been attached to end.
329  *      %CANQUEUE_NOTIFY_FILTCH (out->in call) - edge filter rules changed
330  *      %CANQUEUE_NOTIFY_ERROR  (out->in call) - error in messages processing.
331  * @context: space to store ends user specific information
332  * @endinfo: space to store some other ends usage specific informations
333  *      mainly for waking-up by the notify calls.
334  *
335  * Structure represents place to connect edges to for CAN communication entity.
336  * The zero, one or more incoming and outgoing edges can be connected to
337  * this structure.
338  */
339 struct canque_ends_t {
340         struct list_head active[CANQUEUE_PRIO_NR];
341         struct list_head idle;
342         struct list_head inlist;
343         spinlock_t ends_lock;   /* spin_lock_irqsave / spin_lock_irqrestore */
344         void (*notify)(struct canque_ends_t *qends, struct canque_edge_t *qedge, int what);
345         void *context;
346         union {
347                 struct {
348                         wait_queue_head_t readq;
349                         wait_queue_head_t writeq;
350                         wait_queue_head_t emptyq;
351                 } fileinfo;
352                 struct {
353                         wait_queue_head_t daemonq;
354                         struct msgobj_t *msgobj;
355                         struct chip_t *chip;
356                 } chipinfo;
357         } endinfo;
358 };
359
360 #define CANQUEUE_NOTIFY_EMPTY 1 /* out -> in - all slots are processed by FIFO out side */
361 #define CANQUEUE_NOTIFY_SPACE 2 /* out -> in - full state negated => there is space for new message */
362 #define CANQUEUE_NOTIFY_PROC  3 /* in -> out - empty state negated => out side is requested to process slots */
363 #define CANQUEUE_NOTIFY_NOUSR 4 /* called with some lock to prevent edge disappear */
364 #define CANQUEUE_NOTIFY_DEAD  5 /*  */
365 #define CANQUEUE_NOTIFY_ATACH 6 /*  */
366 #define CANQUEUE_NOTIFY_FILTCH 7 /* filter changed */
367 #define CANQUEUE_NOTIFY_ERROR      0x10000 /* error notifiers */
368 #define CANQUEUE_NOTIFY_ERRTX_PREP 0x11001 /* tx preparation error */
369 #define CANQUEUE_NOTIFY_ERRTX_SEND 0x11002 /* tx send error */
370 #define CANQUEUE_NOTIFY_ERRTX_BUS  0x11003 /* tx bus error */
371
372 /**
373  * canque_notify_inends - request to send notification to the input ends
374  * @qedge: pointer to the edge structure
375  * @what: notification type
376  */
377 static inline
378 void canque_notify_inends(struct canque_edge_t *qedge, int what)
379 {
380         if(qedge->inends)
381                 if(qedge->inends->notify)
382                         qedge->inends->notify(qedge->inends,qedge,what);
383 }
384
385 /**
386  * canque_notify_outends - request to send notification to the output ends
387  * @qedge: pointer to the edge structure
388  * @what: notification type
389  */
390 static inline
391 void canque_notify_outends(struct canque_edge_t *qedge, int what)
392 {
393         if(qedge->outends)
394                 if(qedge->outends->notify)
395                         qedge->outends->notify(qedge->outends,qedge,what);
396 }
397
398 /**
399  * canque_notify_bothends - request to send notification to the both ends
400  * @qedge: pointer to the edge structure
401  * @what: notification type
402  */
403 static inline
404 void canque_notify_bothends(struct canque_edge_t *qedge, int what)
405 {
406         canque_notify_inends(qedge, what);
407         canque_notify_outends(qedge, what);
408 }
409
410 /**
411  * canque_activate_edge - mark output end of the edge as active
412  * @qedge: pointer to the edge structure
413  * @inends: input side of the edge
414  *
415  * Function call moves output side of the edge from idle onto active edges
416  * list.
417  */
418 static inline
419 void canque_activate_edge(struct canque_ends_t *inends, struct canque_edge_t *qedge)
420 {
421         unsigned long flags;
422         struct canque_ends_t *outends;
423         if(qedge->edge_prio>=CANQUEUE_PRIO_NR)
424                 qedge->edge_prio=CANQUEUE_PRIO_NR-1;
425         spin_lock_irqsave(&inends->ends_lock, flags);
426         if((outends=qedge->outends)){
427                 spin_lock(&outends->ends_lock);
428                 spin_lock(&qedge->fifo.fifo_lock);
429                 if(!canque_fifo_test_fl(&qedge->fifo,EMPTY)){
430                         list_del(&qedge->outpeers);
431                         list_add_tail(&qedge->outpeers,&outends->active[qedge->edge_prio]);
432                 }
433                 spin_unlock(&qedge->fifo.fifo_lock);
434                 spin_unlock(&outends->ends_lock);
435
436         }
437         spin_unlock_irqrestore(&inends->ends_lock, flags);
438 }
439
440 /**
441  * canque_filtid2internal - converts message ID and filter flags into internal format
442  * @qedge: pointer to the edge structure
443  * @inends: input side of the edge
444  *
445  * This function maps message ID and %MSG_RTR, %MSG_EXT and %MSG_LOCAL into one 32 bit number
446  */
447 static inline
448 unsigned int canque_filtid2internal(unsigned long id, int filtflags)
449 {
450         filtflags &= MSG_RTR|MSG_EXT|MSG_LOCAL;
451         filtflags += filtflags&MSG_RTR;
452         return (id&MSG_ID_MASK) | (filtflags<<28);
453 }
454
455 int canque_get_inslot(struct canque_ends_t *qends,
456         struct canque_edge_t **qedgep, struct canque_slot_t **slotp, int cmd);
457         
458 int canque_get_inslot4id(struct canque_ends_t *qends,
459         struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
460         int cmd, unsigned long id, int prio);
461         
462 int canque_put_inslot(struct canque_ends_t *qends,
463         struct canque_edge_t *qedge, struct canque_slot_t *slot);
464
465 int canque_abort_inslot(struct canque_ends_t *qends,
466         struct canque_edge_t *qedge, struct canque_slot_t *slot);
467
468 int canque_filter_msg2edges(struct canque_ends_t *qends, struct canmsg_t *msg);
469
470 int canque_test_outslot(struct canque_ends_t *qends,
471         struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
472
473 int canque_free_outslot(struct canque_ends_t *qends,
474         struct canque_edge_t *qedge, struct canque_slot_t *slot);
475
476 int canque_again_outslot(struct canque_ends_t *qends,
477         struct canque_edge_t *qedge, struct canque_slot_t *slot);
478
479 int canque_set_filt(struct canque_edge_t *qedge,
480         unsigned long filtid, unsigned long filtmask, int flags);
481         
482 int canque_flush(struct canque_edge_t *qedge);
483
484 struct canque_edge_t *canque_new_edge_kern(int slotsnr);
485
486 int canque_get_inslot4id_wait_kern(struct canque_ends_t *qends,
487         struct canque_edge_t **qedgep, struct canque_slot_t **slotp,
488         int cmd, unsigned long id, int prio);
489
490 int canque_get_outslot_wait_kern(struct canque_ends_t *qends,
491         struct canque_edge_t **qedgep, struct canque_slot_t **slotp);
492
493 int canque_sync_wait_kern(struct canque_ends_t *qends, struct canque_edge_t *qedge);
494
495 int canqueue_connect_edge(struct canque_edge_t *qedge, struct canque_ends_t *inends, struct canque_ends_t *outends);
496
497 int canqueue_ends_init_gen(struct canque_ends_t *qends);
498
499 int canqueue_ends_init_kern(struct canque_ends_t *qends);
500
501 int canqueue_ends_done_kern(struct canque_ends_t *qends, int sync);
502
503 #endif /*_CAN_QUEUE_H*/