Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[linux-2.6] / drivers / isdn / hardware / eicon / dqueue.c
1 /* $Id: dqueue.c,v 1.5 2003/04/12 21:40:49 schindler Exp $
2  *
3  * Driver for Eicon DIVA Server ISDN cards.
4  * User Mode IDI Interface
5  *
6  * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7  * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8  *
9  * This software may be used and distributed according to the terms
10  * of the GNU General Public License, incorporated herein by reference.
11  */
12
13 #include "platform.h"
14 #include "dqueue.h"
15
16 int
17 diva_data_q_init(diva_um_idi_data_queue_t * q,
18                  int max_length, int max_segments)
19 {
20         int i;
21
22         q->max_length = max_length;
23         q->segments = max_segments;
24
25         for (i = 0; i < q->segments; i++) {
26                 q->data[i] = NULL;
27                 q->length[i] = 0;
28         }
29         q->read = q->write = q->count = q->segment_pending = 0;
30
31         for (i = 0; i < q->segments; i++) {
32                 if (!(q->data[i] = diva_os_malloc(0, q->max_length))) {
33                         diva_data_q_finit(q);
34                         return (-1);
35                 }
36         }
37
38         return (0);
39 }
40
41 int diva_data_q_finit(diva_um_idi_data_queue_t * q)
42 {
43         int i;
44
45         for (i = 0; i < q->segments; i++) {
46                 if (q->data[i]) {
47                         diva_os_free(0, q->data[i]);
48                 }
49                 q->data[i] = NULL;
50                 q->length[i] = 0;
51         }
52         q->read = q->write = q->count = q->segment_pending = 0;
53
54         return (0);
55 }
56
57 int diva_data_q_get_max_length(const diva_um_idi_data_queue_t * q)
58 {
59         return (q->max_length);
60 }
61
62 void *diva_data_q_get_segment4write(diva_um_idi_data_queue_t * q)
63 {
64         if ((!q->segment_pending) && (q->count < q->segments)) {
65                 q->segment_pending = 1;
66                 return (q->data[q->write]);
67         }
68
69         return NULL;
70 }
71
72 void
73 diva_data_q_ack_segment4write(diva_um_idi_data_queue_t * q, int length)
74 {
75         if (q->segment_pending) {
76                 q->length[q->write] = length;
77                 q->count++;
78                 q->write++;
79                 if (q->write >= q->segments) {
80                         q->write = 0;
81                 }
82                 q->segment_pending = 0;
83         }
84 }
85
86 const void *diva_data_q_get_segment4read(const diva_um_idi_data_queue_t *
87                                          q)
88 {
89         if (q->count) {
90                 return (q->data[q->read]);
91         }
92         return NULL;
93 }
94
95 int diva_data_q_get_segment_length(const diva_um_idi_data_queue_t * q)
96 {
97         return (q->length[q->read]);
98 }
99
100 void diva_data_q_ack_segment4read(diva_um_idi_data_queue_t * q)
101 {
102         if (q->count) {
103                 q->length[q->read] = 0;
104                 q->count--;
105                 q->read++;
106                 if (q->read >= q->segments) {
107                         q->read = 0;
108                 }
109         }
110 }