Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[pandora-kernel.git] / drivers / isdn / gigaset / isocdata.c
1 /*
2  * Common data handling layer for bas_gigaset
3  *
4  * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
5  *                       Hansjoerg Lipp <hjlipp@web.de>.
6  *
7  * =====================================================================
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License as
10  *      published by the Free Software Foundation; either version 2 of
11  *      the License, or (at your option) any later version.
12  * =====================================================================
13  */
14
15 #include "gigaset.h"
16 #include <linux/crc-ccitt.h>
17 #include <linux/bitrev.h>
18
19 /* access methods for isowbuf_t */
20 /* ============================ */
21
22 /* initialize buffer structure
23  */
24 void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle)
25 {
26         iwb->read = 0;
27         iwb->nextread = 0;
28         iwb->write = 0;
29         atomic_set(&iwb->writesem, 1);
30         iwb->wbits = 0;
31         iwb->idle = idle;
32         memset(iwb->data + BAS_OUTBUFSIZE, idle, BAS_OUTBUFPAD);
33 }
34
35 /* compute number of bytes which can be appended to buffer
36  * so that there is still room to append a maximum frame of flags
37  */
38 static inline int isowbuf_freebytes(struct isowbuf_t *iwb)
39 {
40         int read, write, freebytes;
41
42         read = iwb->read;
43         write = iwb->write;
44         if ((freebytes = read - write) > 0) {
45                 /* no wraparound: need padding space within regular area */
46                 return freebytes - BAS_OUTBUFPAD;
47         } else if (read < BAS_OUTBUFPAD) {
48                 /* wraparound: can use space up to end of regular area */
49                 return BAS_OUTBUFSIZE - write;
50         } else {
51                 /* following the wraparound yields more space */
52                 return freebytes + BAS_OUTBUFSIZE - BAS_OUTBUFPAD;
53         }
54 }
55
56 /* compare two offsets within the buffer
57  * The buffer is seen as circular, with the read position as start
58  * returns -1/0/1 if position a </=/> position b without crossing 'read'
59  */
60 static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b)
61 {
62         int read;
63         if (a == b)
64                 return 0;
65         read = iwb->read;
66         if (a < b) {
67                 if (a < read && read <= b)
68                         return +1;
69                 else
70                         return -1;
71         } else {
72                 if (b < read && read <= a)
73                         return -1;
74                 else
75                         return +1;
76         }
77 }
78
79 /* start writing
80  * acquire the write semaphore
81  * return true if acquired, false if busy
82  */
83 static inline int isowbuf_startwrite(struct isowbuf_t *iwb)
84 {
85         if (!atomic_dec_and_test(&iwb->writesem)) {
86                 atomic_inc(&iwb->writesem);
87                 gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore",
88                         __func__);
89                 return 0;
90         }
91         gig_dbg(DEBUG_ISO,
92                 "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d",
93                 __func__, iwb->data[iwb->write], iwb->wbits);
94         return 1;
95 }
96
97 /* finish writing
98  * release the write semaphore
99  * returns the current write position
100  */
101 static inline int isowbuf_donewrite(struct isowbuf_t *iwb)
102 {
103         int write = iwb->write;
104         atomic_inc(&iwb->writesem);
105         return write;
106 }
107
108 /* append bits to buffer without any checks
109  * - data contains bits to append, starting at LSB
110  * - nbits is number of bits to append (0..24)
111  * must be called with the write semaphore held
112  * If more than nbits bits are set in data, the extraneous bits are set in the
113  * buffer too, but the write position is only advanced by nbits.
114  */
115 static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits)
116 {
117         int write = iwb->write;
118         data <<= iwb->wbits;
119         data |= iwb->data[write];
120         nbits += iwb->wbits;
121         while (nbits >= 8) {
122                 iwb->data[write++] = data & 0xff;
123                 write %= BAS_OUTBUFSIZE;
124                 data >>= 8;
125                 nbits -= 8;
126         }
127         iwb->wbits = nbits;
128         iwb->data[write] = data & 0xff;
129         iwb->write = write;
130 }
131
132 /* put final flag on HDLC bitstream
133  * also sets the idle fill byte to the correspondingly shifted flag pattern
134  * must be called with the write semaphore held
135  */
136 static inline void isowbuf_putflag(struct isowbuf_t *iwb)
137 {
138         int write;
139
140         /* add two flags, thus reliably covering one byte */
141         isowbuf_putbits(iwb, 0x7e7e, 8);
142         /* recover the idle flag byte */
143         write = iwb->write;
144         iwb->idle = iwb->data[write];
145         gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle);
146         /* mask extraneous bits in buffer */
147         iwb->data[write] &= (1 << iwb->wbits) - 1;
148 }
149
150 /* retrieve a block of bytes for sending
151  * The requested number of bytes is provided as a contiguous block.
152  * If necessary, the frame is filled to the requested number of bytes
153  * with the idle value.
154  * returns offset to frame, < 0 on busy or error
155  */
156 int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size)
157 {
158         int read, write, limit, src, dst;
159         unsigned char pbyte;
160
161         read = iwb->nextread;
162         write = iwb->write;
163         if (likely(read == write)) {
164                 /* return idle frame */
165                 return read < BAS_OUTBUFPAD ?
166                         BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD;
167         }
168
169         limit = read + size;
170         gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d",
171                 __func__, read, write, limit);
172 #ifdef CONFIG_GIGASET_DEBUG
173         if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) {
174                 pr_err("invalid size %d\n", size);
175                 return -EINVAL;
176         }
177         src = iwb->read;
178         if (unlikely(limit >= BAS_OUTBUFSIZE + BAS_OUTBUFPAD ||
179                      (read < src && limit >= src))) {
180                 pr_err("isoc write buffer frame reservation violated\n");
181                 return -EFAULT;
182         }
183 #endif
184
185         if (read < write) {
186                 /* no wraparound in valid data */
187                 if (limit >= write) {
188                         /* append idle frame */
189                         if (!isowbuf_startwrite(iwb))
190                                 return -EBUSY;
191                         /* write position could have changed */
192                         write = iwb->write;
193                         if (limit >= write) {
194                                 pbyte = iwb->data[write]; /* save
195                                                              partial byte */
196                                 limit = write + BAS_OUTBUFPAD;
197                                 gig_dbg(DEBUG_STREAM,
198                                         "%s: filling %d->%d with %02x",
199                                         __func__, write, limit, iwb->idle);
200                                 if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE)
201                                         memset(iwb->data + write, iwb->idle,
202                                                BAS_OUTBUFPAD);
203                                 else {
204                                         /* wraparound, fill entire pad area */
205                                         memset(iwb->data + write, iwb->idle,
206                                                BAS_OUTBUFSIZE + BAS_OUTBUFPAD
207                                                - write);
208                                         limit = 0;
209                                 }
210                                 gig_dbg(DEBUG_STREAM,
211                                         "%s: restoring %02x at %d",
212                                         __func__, pbyte, limit);
213                                 iwb->data[limit] = pbyte; /* restore
214                                                              partial byte */
215                                 iwb->write = limit;
216                         }
217                         isowbuf_donewrite(iwb);
218                 }
219         } else {
220                 /* valid data wraparound */
221                 if (limit >= BAS_OUTBUFSIZE) {
222                         /* copy wrapped part into pad area */
223                         src = 0;
224                         dst = BAS_OUTBUFSIZE;
225                         while (dst < limit && src < write)
226                                 iwb->data[dst++] = iwb->data[src++];
227                         if (dst <= limit) {
228                                 /* fill pad area with idle byte */
229                                 memset(iwb->data + dst, iwb->idle,
230                                        BAS_OUTBUFSIZE + BAS_OUTBUFPAD - dst);
231                         }
232                         limit = src;
233                 }
234         }
235         iwb->nextread = limit;
236         return read;
237 }
238
239 /* dump_bytes
240  * write hex bytes to syslog for debugging
241  */
242 static inline void dump_bytes(enum debuglevel level, const char *tag,
243                               unsigned char *bytes, int count)
244 {
245 #ifdef CONFIG_GIGASET_DEBUG
246         unsigned char c;
247         static char dbgline[3 * 32 + 1];
248         int i = 0;
249
250         if (!(gigaset_debuglevel & level))
251                 return;
252
253         while (count-- > 0) {
254                 if (i > sizeof(dbgline) - 4) {
255                         dbgline[i] = '\0';
256                         gig_dbg(level, "%s:%s", tag, dbgline);
257                         i = 0;
258                 }
259                 c = *bytes++;
260                 dbgline[i] = (i && !(i % 12)) ? '-' : ' ';
261                 i++;
262                 dbgline[i++] = hex_asc_hi(c);
263                 dbgline[i++] = hex_asc_lo(c);
264         }
265         dbgline[i] = '\0';
266         gig_dbg(level, "%s:%s", tag, dbgline);
267 #endif
268 }
269
270 /*============================================================================*/
271
272 /* bytewise HDLC bitstuffing via table lookup
273  * lookup table: 5 subtables for 0..4 preceding consecutive '1' bits
274  * index: 256*(number of preceding '1' bits) + (next byte to stuff)
275  * value: bit  9.. 0 = result bits
276  *        bit 12..10 = number of trailing '1' bits in result
277  *        bit 14..13 = number of bits added by stuffing
278  */
279 static const u16 stufftab[5 * 256] = {
280 // previous 1s = 0:
281  0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
282  0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x201f,
283  0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
284  0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x205f,
285  0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
286  0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x209f,
287  0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
288  0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20df,
289  0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f,
290  0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x251f,
291  0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af,
292  0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x255f,
293  0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x08cf,
294  0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x299f,
295  0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x0cef,
296  0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x2ddf,
297
298 // previous 1s = 1:
299  0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x200f,
300  0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x202f,
301  0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x204f,
302  0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x206f,
303  0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x208f,
304  0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20af,
305  0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20cf,
306  0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20ef,
307  0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x250f,
308  0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x252f,
309  0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x254f,
310  0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x256f,
311  0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x08c7, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x298f,
312  0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x08d7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29af,
313  0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dcf,
314  0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x10f7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x31ef,
315
316 // previous 1s = 2:
317  0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x2007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x2017,
318  0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x2027, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x2037,
319  0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x2047, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x2057,
320  0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x2067, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x203e, 0x2077,
321  0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x2087, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x2097,
322  0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x20a7, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x20b7,
323  0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x20c7, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x20d7,
324  0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x20e7, 0x0078, 0x0079, 0x007a, 0x007b, 0x207c, 0x207d, 0x20be, 0x20f7,
325  0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x2507, 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x2517,
326  0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x2527, 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x2537,
327  0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x2547, 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x2557,
328  0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x2567, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x253e, 0x2577,
329  0x08c0, 0x08c1, 0x08c2, 0x08c3, 0x08c4, 0x08c5, 0x08c6, 0x2987, 0x08c8, 0x08c9, 0x08ca, 0x08cb, 0x08cc, 0x08cd, 0x08ce, 0x2997,
330  0x08d0, 0x08d1, 0x08d2, 0x08d3, 0x08d4, 0x08d5, 0x08d6, 0x29a7, 0x08d8, 0x08d9, 0x08da, 0x08db, 0x08dc, 0x08dd, 0x08de, 0x29b7,
331  0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dc7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced, 0x0cee, 0x2dd7,
332  0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6, 0x31e7, 0x20f8, 0x20f9, 0x20fa, 0x20fb, 0x257c, 0x257d, 0x29be, 0x41f7,
333
334 // previous 1s = 3:
335  0x0000, 0x0001, 0x0002, 0x2003, 0x0004, 0x0005, 0x0006, 0x200b, 0x0008, 0x0009, 0x000a, 0x2013, 0x000c, 0x000d, 0x000e, 0x201b,
336  0x0010, 0x0011, 0x0012, 0x2023, 0x0014, 0x0015, 0x0016, 0x202b, 0x0018, 0x0019, 0x001a, 0x2033, 0x001c, 0x001d, 0x001e, 0x203b,
337  0x0020, 0x0021, 0x0022, 0x2043, 0x0024, 0x0025, 0x0026, 0x204b, 0x0028, 0x0029, 0x002a, 0x2053, 0x002c, 0x002d, 0x002e, 0x205b,
338  0x0030, 0x0031, 0x0032, 0x2063, 0x0034, 0x0035, 0x0036, 0x206b, 0x0038, 0x0039, 0x003a, 0x2073, 0x003c, 0x003d, 0x203e, 0x207b,
339  0x0040, 0x0041, 0x0042, 0x2083, 0x0044, 0x0045, 0x0046, 0x208b, 0x0048, 0x0049, 0x004a, 0x2093, 0x004c, 0x004d, 0x004e, 0x209b,
340  0x0050, 0x0051, 0x0052, 0x20a3, 0x0054, 0x0055, 0x0056, 0x20ab, 0x0058, 0x0059, 0x005a, 0x20b3, 0x005c, 0x005d, 0x005e, 0x20bb,
341  0x0060, 0x0061, 0x0062, 0x20c3, 0x0064, 0x0065, 0x0066, 0x20cb, 0x0068, 0x0069, 0x006a, 0x20d3, 0x006c, 0x006d, 0x006e, 0x20db,
342  0x0070, 0x0071, 0x0072, 0x20e3, 0x0074, 0x0075, 0x0076, 0x20eb, 0x0078, 0x0079, 0x007a, 0x20f3, 0x207c, 0x207d, 0x20be, 0x40fb,
343  0x0480, 0x0481, 0x0482, 0x2503, 0x0484, 0x0485, 0x0486, 0x250b, 0x0488, 0x0489, 0x048a, 0x2513, 0x048c, 0x048d, 0x048e, 0x251b,
344  0x0490, 0x0491, 0x0492, 0x2523, 0x0494, 0x0495, 0x0496, 0x252b, 0x0498, 0x0499, 0x049a, 0x2533, 0x049c, 0x049d, 0x049e, 0x253b,
345  0x04a0, 0x04a1, 0x04a2, 0x2543, 0x04a4, 0x04a5, 0x04a6, 0x254b, 0x04a8, 0x04a9, 0x04aa, 0x2553, 0x04ac, 0x04ad, 0x04ae, 0x255b,
346  0x04b0, 0x04b1, 0x04b2, 0x2563, 0x04b4, 0x04b5, 0x04b6, 0x256b, 0x04b8, 0x04b9, 0x04ba, 0x2573, 0x04bc, 0x04bd, 0x253e, 0x257b,
347  0x08c0, 0x08c1, 0x08c2, 0x2983, 0x08c4, 0x08c5, 0x08c6, 0x298b, 0x08c8, 0x08c9, 0x08ca, 0x2993, 0x08cc, 0x08cd, 0x08ce, 0x299b,
348  0x08d0, 0x08d1, 0x08d2, 0x29a3, 0x08d4, 0x08d5, 0x08d6, 0x29ab, 0x08d8, 0x08d9, 0x08da, 0x29b3, 0x08dc, 0x08dd, 0x08de, 0x29bb,
349  0x0ce0, 0x0ce1, 0x0ce2, 0x2dc3, 0x0ce4, 0x0ce5, 0x0ce6, 0x2dcb, 0x0ce8, 0x0ce9, 0x0cea, 0x2dd3, 0x0cec, 0x0ced, 0x0cee, 0x2ddb,
350  0x10f0, 0x10f1, 0x10f2, 0x31e3, 0x10f4, 0x10f5, 0x10f6, 0x31eb, 0x20f8, 0x20f9, 0x20fa, 0x41f3, 0x257c, 0x257d, 0x29be, 0x46fb,
351
352 // previous 1s = 4:
353  0x0000, 0x2001, 0x0002, 0x2005, 0x0004, 0x2009, 0x0006, 0x200d, 0x0008, 0x2011, 0x000a, 0x2015, 0x000c, 0x2019, 0x000e, 0x201d,
354  0x0010, 0x2021, 0x0012, 0x2025, 0x0014, 0x2029, 0x0016, 0x202d, 0x0018, 0x2031, 0x001a, 0x2035, 0x001c, 0x2039, 0x001e, 0x203d,
355  0x0020, 0x2041, 0x0022, 0x2045, 0x0024, 0x2049, 0x0026, 0x204d, 0x0028, 0x2051, 0x002a, 0x2055, 0x002c, 0x2059, 0x002e, 0x205d,
356  0x0030, 0x2061, 0x0032, 0x2065, 0x0034, 0x2069, 0x0036, 0x206d, 0x0038, 0x2071, 0x003a, 0x2075, 0x003c, 0x2079, 0x203e, 0x407d,
357  0x0040, 0x2081, 0x0042, 0x2085, 0x0044, 0x2089, 0x0046, 0x208d, 0x0048, 0x2091, 0x004a, 0x2095, 0x004c, 0x2099, 0x004e, 0x209d,
358  0x0050, 0x20a1, 0x0052, 0x20a5, 0x0054, 0x20a9, 0x0056, 0x20ad, 0x0058, 0x20b1, 0x005a, 0x20b5, 0x005c, 0x20b9, 0x005e, 0x20bd,
359  0x0060, 0x20c1, 0x0062, 0x20c5, 0x0064, 0x20c9, 0x0066, 0x20cd, 0x0068, 0x20d1, 0x006a, 0x20d5, 0x006c, 0x20d9, 0x006e, 0x20dd,
360  0x0070, 0x20e1, 0x0072, 0x20e5, 0x0074, 0x20e9, 0x0076, 0x20ed, 0x0078, 0x20f1, 0x007a, 0x20f5, 0x207c, 0x40f9, 0x20be, 0x417d,
361  0x0480, 0x2501, 0x0482, 0x2505, 0x0484, 0x2509, 0x0486, 0x250d, 0x0488, 0x2511, 0x048a, 0x2515, 0x048c, 0x2519, 0x048e, 0x251d,
362  0x0490, 0x2521, 0x0492, 0x2525, 0x0494, 0x2529, 0x0496, 0x252d, 0x0498, 0x2531, 0x049a, 0x2535, 0x049c, 0x2539, 0x049e, 0x253d,
363  0x04a0, 0x2541, 0x04a2, 0x2545, 0x04a4, 0x2549, 0x04a6, 0x254d, 0x04a8, 0x2551, 0x04aa, 0x2555, 0x04ac, 0x2559, 0x04ae, 0x255d,
364  0x04b0, 0x2561, 0x04b2, 0x2565, 0x04b4, 0x2569, 0x04b6, 0x256d, 0x04b8, 0x2571, 0x04ba, 0x2575, 0x04bc, 0x2579, 0x253e, 0x467d,
365  0x08c0, 0x2981, 0x08c2, 0x2985, 0x08c4, 0x2989, 0x08c6, 0x298d, 0x08c8, 0x2991, 0x08ca, 0x2995, 0x08cc, 0x2999, 0x08ce, 0x299d,
366  0x08d0, 0x29a1, 0x08d2, 0x29a5, 0x08d4, 0x29a9, 0x08d6, 0x29ad, 0x08d8, 0x29b1, 0x08da, 0x29b5, 0x08dc, 0x29b9, 0x08de, 0x29bd,
367  0x0ce0, 0x2dc1, 0x0ce2, 0x2dc5, 0x0ce4, 0x2dc9, 0x0ce6, 0x2dcd, 0x0ce8, 0x2dd1, 0x0cea, 0x2dd5, 0x0cec, 0x2dd9, 0x0cee, 0x2ddd,
368  0x10f0, 0x31e1, 0x10f2, 0x31e5, 0x10f4, 0x31e9, 0x10f6, 0x31ed, 0x20f8, 0x41f1, 0x20fa, 0x41f5, 0x257c, 0x46f9, 0x29be, 0x4b7d
369 };
370
371 /* hdlc_bitstuff_byte
372  * perform HDLC bitstuffing for one input byte (8 bits, LSB first)
373  * parameters:
374  *      cin     input byte
375  *      ones    number of trailing '1' bits in result before this step
376  *      iwb     pointer to output buffer structure (write semaphore must be held)
377  * return value:
378  *      number of trailing '1' bits in result after this step
379  */
380
381 static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin,
382                                      int ones)
383 {
384         u16 stuff;
385         int shiftinc, newones;
386
387         /* get stuffing information for input byte
388          * value: bit  9.. 0 = result bits
389          *        bit 12..10 = number of trailing '1' bits in result
390          *        bit 14..13 = number of bits added by stuffing
391          */
392         stuff = stufftab[256 * ones + cin];
393         shiftinc = (stuff >> 13) & 3;
394         newones = (stuff >> 10) & 7;
395         stuff &= 0x3ff;
396
397         /* append stuffed byte to output stream */
398         isowbuf_putbits(iwb, stuff, 8 + shiftinc);
399         return newones;
400 }
401
402 /* hdlc_buildframe
403  * Perform HDLC framing with bitstuffing on a byte buffer
404  * The input buffer is regarded as a sequence of bits, starting with the least
405  * significant bit of the first byte and ending with the most significant bit
406  * of the last byte. A 16 bit FCS is appended as defined by RFC 1662.
407  * Whenever five consecutive '1' bits appear in the resulting bit sequence, a
408  * '0' bit is inserted after them.
409  * The resulting bit string and a closing flag pattern (PPP_FLAG, '01111110')
410  * are appended to the output buffer starting at the given bit position, which
411  * is assumed to already contain a leading flag.
412  * The output buffer must have sufficient length; count + count/5 + 6 bytes
413  * starting at *out are safe and are verified to be present.
414  * parameters:
415  *      in      input buffer
416  *      count   number of bytes in input buffer
417  *      iwb     pointer to output buffer structure (write semaphore must be held)
418  * return value:
419  *      position of end of packet in output buffer on success,
420  *      -EAGAIN if write semaphore busy or buffer full
421  */
422
423 static inline int hdlc_buildframe(struct isowbuf_t *iwb,
424                                   unsigned char *in, int count)
425 {
426         int ones;
427         u16 fcs;
428         int end;
429         unsigned char c;
430
431         if (isowbuf_freebytes(iwb) < count + count / 5 + 6 ||
432             !isowbuf_startwrite(iwb)) {
433                 gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN",
434                         __func__, isowbuf_freebytes(iwb));
435                 return -EAGAIN;
436         }
437
438         dump_bytes(DEBUG_STREAM, "snd data", in, count);
439
440         /* bitstuff and checksum input data */
441         fcs = PPP_INITFCS;
442         ones = 0;
443         while (count-- > 0) {
444                 c = *in++;
445                 ones = hdlc_bitstuff_byte(iwb, c, ones);
446                 fcs = crc_ccitt_byte(fcs, c);
447         }
448
449         /* bitstuff and append FCS (complemented, least significant byte first) */
450         fcs ^= 0xffff;
451         ones = hdlc_bitstuff_byte(iwb, fcs & 0x00ff, ones);
452         ones = hdlc_bitstuff_byte(iwb, (fcs >> 8) & 0x00ff, ones);
453
454         /* put closing flag and repeat byte for flag idle */
455         isowbuf_putflag(iwb);
456         end = isowbuf_donewrite(iwb);
457         dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1);
458         return end;
459 }
460
461 /* trans_buildframe
462  * Append a block of 'transparent' data to the output buffer,
463  * inverting the bytes.
464  * The output buffer must have sufficient length; count bytes
465  * starting at *out are safe and are verified to be present.
466  * parameters:
467  *      in      input buffer
468  *      count   number of bytes in input buffer
469  *      iwb     pointer to output buffer structure (write semaphore must be held)
470  * return value:
471  *      position of end of packet in output buffer on success,
472  *      -EAGAIN if write semaphore busy or buffer full
473  */
474
475 static inline int trans_buildframe(struct isowbuf_t *iwb,
476                                    unsigned char *in, int count)
477 {
478         int write;
479         unsigned char c;
480
481         if (unlikely(count <= 0))
482                 return iwb->write;
483
484         if (isowbuf_freebytes(iwb) < count ||
485             !isowbuf_startwrite(iwb)) {
486                 gig_dbg(DEBUG_ISO, "can't put %d bytes", count);
487                 return -EAGAIN;
488         }
489
490         gig_dbg(DEBUG_STREAM, "put %d bytes", count);
491         write = iwb->write;
492         do {
493                 c = bitrev8(*in++);
494                 iwb->data[write++] = c;
495                 write %= BAS_OUTBUFSIZE;
496         } while (--count > 0);
497         iwb->write = write;
498         iwb->idle = c;
499
500         return isowbuf_donewrite(iwb);
501 }
502
503 int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len)
504 {
505         int result;
506
507         switch (bcs->proto2) {
508         case ISDN_PROTO_L2_HDLC:
509                 result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len);
510                 gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d",
511                         __func__, len, result);
512                 break;
513         default:                        /* assume transparent */
514                 result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len);
515                 gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d",
516                         __func__, len, result);
517         }
518         return result;
519 }
520
521 /* hdlc_putbyte
522  * append byte c to current skb of B channel structure *bcs, updating fcs
523  */
524 static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs)
525 {
526         bcs->fcs = crc_ccitt_byte(bcs->fcs, c);
527         if (unlikely(bcs->skb == NULL)) {
528                 /* skipping */
529                 return;
530         }
531         if (unlikely(bcs->skb->len == SBUFSIZE)) {
532                 dev_warn(bcs->cs->dev, "received oversized packet discarded\n");
533                 bcs->hw.bas->giants++;
534                 dev_kfree_skb_any(bcs->skb);
535                 bcs->skb = NULL;
536                 return;
537         }
538         *__skb_put(bcs->skb, 1) = c;
539 }
540
541 /* hdlc_flush
542  * drop partial HDLC data packet
543  */
544 static inline void hdlc_flush(struct bc_state *bcs)
545 {
546         /* clear skb or allocate new if not skipping */
547         if (likely(bcs->skb != NULL))
548                 skb_trim(bcs->skb, 0);
549         else if (!bcs->ignore) {
550                 if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
551                         skb_reserve(bcs->skb, HW_HDR_LEN);
552                 else
553                         dev_err(bcs->cs->dev, "could not allocate skb\n");
554         }
555
556         /* reset packet state */
557         bcs->fcs = PPP_INITFCS;
558 }
559
560 /* hdlc_done
561  * process completed HDLC data packet
562  */
563 static inline void hdlc_done(struct bc_state *bcs)
564 {
565         struct sk_buff *procskb;
566
567         if (unlikely(bcs->ignore)) {
568                 bcs->ignore--;
569                 hdlc_flush(bcs);
570                 return;
571         }
572
573         if ((procskb = bcs->skb) == NULL) {
574                 /* previous error */
575                 gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__);
576                 gigaset_rcv_error(NULL, bcs->cs, bcs);
577         } else if (procskb->len < 2) {
578                 dev_notice(bcs->cs->dev, "received short frame (%d octets)\n",
579                            procskb->len);
580                 bcs->hw.bas->runts++;
581                 gigaset_rcv_error(procskb, bcs->cs, bcs);
582         } else if (bcs->fcs != PPP_GOODFCS) {
583                 dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n",
584                            bcs->fcs);
585                 bcs->hw.bas->fcserrs++;
586                 gigaset_rcv_error(procskb, bcs->cs, bcs);
587         } else {
588                 procskb->len -= 2;              /* subtract FCS */
589                 procskb->tail -= 2;
590                 gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)",
591                         __func__, procskb->len);
592                 dump_bytes(DEBUG_STREAM,
593                            "rcv data", procskb->data, procskb->len);
594                 bcs->hw.bas->goodbytes += procskb->len;
595                 gigaset_rcv_skb(procskb, bcs->cs, bcs);
596         }
597
598         if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
599                 skb_reserve(bcs->skb, HW_HDR_LEN);
600         else
601                 dev_err(bcs->cs->dev, "could not allocate skb\n");
602         bcs->fcs = PPP_INITFCS;
603 }
604
605 /* hdlc_frag
606  * drop HDLC data packet with non-integral last byte
607  */
608 static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits)
609 {
610         if (unlikely(bcs->ignore)) {
611                 bcs->ignore--;
612                 hdlc_flush(bcs);
613                 return;
614         }
615
616         dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits);
617         bcs->hw.bas->alignerrs++;
618         gigaset_rcv_error(bcs->skb, bcs->cs, bcs);
619
620         if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)
621                 skb_reserve(bcs->skb, HW_HDR_LEN);
622         else
623                 dev_err(bcs->cs->dev, "could not allocate skb\n");
624         bcs->fcs = PPP_INITFCS;
625 }
626
627 /* bit counts lookup table for HDLC bit unstuffing
628  * index: input byte
629  * value: bit 0..3 = number of consecutive '1' bits starting from LSB
630  *        bit 4..6 = number of consecutive '1' bits starting from MSB
631  *                   (replacing 8 by 7 to make it fit; the algorithm won't care)
632  *        bit 7 set if there are 5 or more "interior" consecutive '1' bits
633  */
634 static const unsigned char bitcounts[256] = {
635   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
636   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
637   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
638   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x80, 0x06,
639   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
640   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05,
641   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04,
642   0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x80, 0x81, 0x80, 0x07,
643   0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
644   0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x15,
645   0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x14,
646   0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x10, 0x13, 0x10, 0x11, 0x10, 0x12, 0x10, 0x11, 0x90, 0x16,
647   0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x24,
648   0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x23, 0x20, 0x21, 0x20, 0x22, 0x20, 0x21, 0x20, 0x25,
649   0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x31, 0x30, 0x34,
650   0x40, 0x41, 0x40, 0x42, 0x40, 0x41, 0x40, 0x43, 0x50, 0x51, 0x50, 0x52, 0x60, 0x61, 0x70, 0x78
651 };
652
653 /* hdlc_unpack
654  * perform HDLC frame processing (bit unstuffing, flag detection, FCS calculation)
655  * on a sequence of received data bytes (8 bits each, LSB first)
656  * pass on successfully received, complete frames as SKBs via gigaset_rcv_skb
657  * notify of errors via gigaset_rcv_error
658  * tally frames, errors etc. in BC structure counters
659  * parameters:
660  *      src     received data
661  *      count   number of received bytes
662  *      bcs     receiving B channel structure
663  */
664 static inline void hdlc_unpack(unsigned char *src, unsigned count,
665                                struct bc_state *bcs)
666 {
667         struct bas_bc_state *ubc = bcs->hw.bas;
668         int inputstate;
669         unsigned seqlen, inbyte, inbits;
670
671         /* load previous state:
672          * inputstate = set of flag bits:
673          * - INS_flag_hunt: no complete opening flag received since connection setup or last abort
674          * - INS_have_data: at least one complete data byte received since last flag
675          * seqlen = number of consecutive '1' bits in last 7 input stream bits (0..7)
676          * inbyte = accumulated partial data byte (if !INS_flag_hunt)
677          * inbits = number of valid bits in inbyte, starting at LSB (0..6)
678          */
679         inputstate = bcs->inputstate;
680         seqlen = ubc->seqlen;
681         inbyte = ubc->inbyte;
682         inbits = ubc->inbits;
683
684         /* bit unstuffing a byte a time
685          * Take your time to understand this; it's straightforward but tedious.
686          * The "bitcounts" lookup table is used to speed up the counting of
687          * leading and trailing '1' bits.
688          */
689         while (count--) {
690                 unsigned char c = *src++;
691                 unsigned char tabentry = bitcounts[c];
692                 unsigned lead1 = tabentry & 0x0f;
693                 unsigned trail1 = (tabentry >> 4) & 0x0f;
694
695                 seqlen += lead1;
696
697                 if (unlikely(inputstate & INS_flag_hunt)) {
698                         if (c == PPP_FLAG) {
699                                 /* flag-in-one */
700                                 inputstate &= ~(INS_flag_hunt | INS_have_data);
701                                 inbyte = 0;
702                                 inbits = 0;
703                         } else if (seqlen == 6 && trail1 != 7) {
704                                 /* flag completed & not followed by abort */
705                                 inputstate &= ~(INS_flag_hunt | INS_have_data);
706                                 inbyte = c >> (lead1 + 1);
707                                 inbits = 7 - lead1;
708                                 if (trail1 >= 8) {
709                                         /* interior stuffing: omitting the MSB handles most cases */
710                                         inbits--;
711                                         /* correct the incorrectly handled cases individually */
712                                         switch (c) {
713                                         case 0xbe:
714                                                 inbyte = 0x3f;
715                                                 break;
716                                         }
717                                 }
718                         }
719                         /* else: continue flag-hunting */
720                 } else if (likely(seqlen < 5 && trail1 < 7)) {
721                         /* streamlined case: 8 data bits, no stuffing */
722                         inbyte |= c << inbits;
723                         hdlc_putbyte(inbyte & 0xff, bcs);
724                         inputstate |= INS_have_data;
725                         inbyte >>= 8;
726                         /* inbits unchanged */
727                 } else if (likely(seqlen == 6 && inbits == 7 - lead1 &&
728                                   trail1 + 1 == inbits &&
729                                   !(inputstate & INS_have_data))) {
730                         /* streamlined case: flag idle - state unchanged */
731                 } else if (unlikely(seqlen > 6)) {
732                         /* abort sequence */
733                         ubc->aborts++;
734                         hdlc_flush(bcs);
735                         inputstate |= INS_flag_hunt;
736                 } else if (seqlen == 6) {
737                         /* closing flag, including (6 - lead1) '1's and one '0' from inbits */
738                         if (inbits > 7 - lead1) {
739                                 hdlc_frag(bcs, inbits + lead1 - 7);
740                                 inputstate &= ~INS_have_data;
741                         } else {
742                                 if (inbits < 7 - lead1)
743                                         ubc->stolen0s ++;
744                                 if (inputstate & INS_have_data) {
745                                         hdlc_done(bcs);
746                                         inputstate &= ~INS_have_data;
747                                 }
748                         }
749
750                         if (c == PPP_FLAG) {
751                                 /* complete flag, LSB overlaps preceding flag */
752                                 ubc->shared0s ++;
753                                 inbits = 0;
754                                 inbyte = 0;
755                         } else if (trail1 != 7) {
756                                 /* remaining bits */
757                                 inbyte = c >> (lead1 + 1);
758                                 inbits = 7 - lead1;
759                                 if (trail1 >= 8) {
760                                         /* interior stuffing: omitting the MSB handles most cases */
761                                         inbits--;
762                                         /* correct the incorrectly handled cases individually */
763                                         switch (c) {
764                                         case 0xbe:
765                                                 inbyte = 0x3f;
766                                                 break;
767                                         }
768                                 }
769                         } else {
770                                 /* abort sequence follows, skb already empty anyway */
771                                 ubc->aborts++;
772                                 inputstate |= INS_flag_hunt;
773                         }
774                 } else { /* (seqlen < 6) && (seqlen == 5 || trail1 >= 7) */
775
776                         if (c == PPP_FLAG) {
777                                 /* complete flag */
778                                 if (seqlen == 5)
779                                         ubc->stolen0s++;
780                                 if (inbits) {
781                                         hdlc_frag(bcs, inbits);
782                                         inbits = 0;
783                                         inbyte = 0;
784                                 } else if (inputstate & INS_have_data)
785                                         hdlc_done(bcs);
786                                 inputstate &= ~INS_have_data;
787                         } else if (trail1 == 7) {
788                                 /* abort sequence */
789                                 ubc->aborts++;
790                                 hdlc_flush(bcs);
791                                 inputstate |= INS_flag_hunt;
792                         } else {
793                                 /* stuffed data */
794                                 if (trail1 < 7) { /* => seqlen == 5 */
795                                         /* stuff bit at position lead1, no interior stuffing */
796                                         unsigned char mask = (1 << lead1) - 1;
797                                         c = (c & mask) | ((c & ~mask) >> 1);
798                                         inbyte |= c << inbits;
799                                         inbits += 7;
800                                 } else if (seqlen < 5) { /* trail1 >= 8 */
801                                         /* interior stuffing: omitting the MSB handles most cases */
802                                         /* correct the incorrectly handled cases individually */
803                                         switch (c) {
804                                         case 0xbe:
805                                                 c = 0x7e;
806                                                 break;
807                                         }
808                                         inbyte |= c << inbits;
809                                         inbits += 7;
810                                 } else { /* seqlen == 5 && trail1 >= 8 */
811
812                                         /* stuff bit at lead1 *and* interior stuffing */
813                                         switch (c) {    /* unstuff individually */
814                                         case 0x7d:
815                                                 c = 0x3f;
816                                                 break;
817                                         case 0xbe:
818                                                 c = 0x3f;
819                                                 break;
820                                         case 0x3e:
821                                                 c = 0x1f;
822                                                 break;
823                                         case 0x7c:
824                                                 c = 0x3e;
825                                                 break;
826                                         }
827                                         inbyte |= c << inbits;
828                                         inbits += 6;
829                                 }
830                                 if (inbits >= 8) {
831                                         inbits -= 8;
832                                         hdlc_putbyte(inbyte & 0xff, bcs);
833                                         inputstate |= INS_have_data;
834                                         inbyte >>= 8;
835                                 }
836                         }
837                 }
838                 seqlen = trail1 & 7;
839         }
840
841         /* save new state */
842         bcs->inputstate = inputstate;
843         ubc->seqlen = seqlen;
844         ubc->inbyte = inbyte;
845         ubc->inbits = inbits;
846 }
847
848 /* trans_receive
849  * pass on received USB frame transparently as SKB via gigaset_rcv_skb
850  * invert bytes
851  * tally frames, errors etc. in BC structure counters
852  * parameters:
853  *      src     received data
854  *      count   number of received bytes
855  *      bcs     receiving B channel structure
856  */
857 static inline void trans_receive(unsigned char *src, unsigned count,
858                                  struct bc_state *bcs)
859 {
860         struct sk_buff *skb;
861         int dobytes;
862         unsigned char *dst;
863
864         if (unlikely(bcs->ignore)) {
865                 bcs->ignore--;
866                 hdlc_flush(bcs);
867                 return;
868         }
869         if (unlikely((skb = bcs->skb) == NULL)) {
870                 bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
871                 if (!skb) {
872                         dev_err(bcs->cs->dev, "could not allocate skb\n");
873                         return;
874                 }
875                 skb_reserve(skb, HW_HDR_LEN);
876         }
877         bcs->hw.bas->goodbytes += skb->len;
878         dobytes = TRANSBUFSIZE - skb->len;
879         while (count > 0) {
880                 dst = skb_put(skb, count < dobytes ? count : dobytes);
881                 while (count > 0 && dobytes > 0) {
882                         *dst++ = bitrev8(*src++);
883                         count--;
884                         dobytes--;
885                 }
886                 if (dobytes == 0) {
887                         gigaset_rcv_skb(skb, bcs->cs, bcs);
888                         bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN);
889                         if (!skb) {
890                                 dev_err(bcs->cs->dev,
891                                         "could not allocate skb\n");
892                                 return;
893                         }
894                         skb_reserve(bcs->skb, HW_HDR_LEN);
895                         dobytes = TRANSBUFSIZE;
896                 }
897         }
898 }
899
900 void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs)
901 {
902         switch (bcs->proto2) {
903         case ISDN_PROTO_L2_HDLC:
904                 hdlc_unpack(src, count, bcs);
905                 break;
906         default:                /* assume transparent */
907                 trans_receive(src, count, bcs);
908         }
909 }
910
911 /* == data input =========================================================== */
912
913 static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf)
914 {
915         struct cardstate *cs = inbuf->cs;
916         unsigned cbytes      = cs->cbytes;
917
918         while (numbytes--) {
919                 /* copy next character, check for end of line */
920                 switch (cs->respdata[cbytes] = *src++) {
921                 case '\r':
922                 case '\n':
923                         /* end of line */
924                         gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
925                                 __func__, cbytes);
926                         if (cbytes >= MAX_RESP_SIZE - 1)
927                                 dev_warn(cs->dev, "response too large\n");
928                         cs->cbytes = cbytes;
929                         gigaset_handle_modem_response(cs);
930                         cbytes = 0;
931                         break;
932                 default:
933                         /* advance in line buffer, checking for overflow */
934                         if (cbytes < MAX_RESP_SIZE - 1)
935                                 cbytes++;
936                 }
937         }
938
939         /* save state */
940         cs->cbytes = cbytes;
941 }
942
943
944 /* process a block of data received through the control channel
945  */
946 void gigaset_isoc_input(struct inbuf_t *inbuf)
947 {
948         struct cardstate *cs = inbuf->cs;
949         unsigned tail, head, numbytes;
950         unsigned char *src;
951
952         head = inbuf->head;
953         while (head != (tail = inbuf->tail)) {
954                 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
955                 if (head > tail)
956                         tail = RBUFSIZE;
957                 src = inbuf->data + head;
958                 numbytes = tail - head;
959                 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
960
961                 if (cs->mstate == MS_LOCKED) {
962                         gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
963                                            numbytes, src);
964                         gigaset_if_receive(inbuf->cs, src, numbytes);
965                 } else {
966                         gigaset_dbg_buffer(DEBUG_CMD, "received response",
967                                            numbytes, src);
968                         cmd_loop(src, numbytes, inbuf);
969                 }
970
971                 head += numbytes;
972                 if (head == RBUFSIZE)
973                         head = 0;
974                 gig_dbg(DEBUG_INTR, "setting head to %u", head);
975                 inbuf->head = head;
976         }
977 }
978
979
980 /* == data output ========================================================== */
981
982 /* gigaset_send_skb
983  * called by common.c to queue an skb for sending
984  * and start transmission if necessary
985  * parameters:
986  *      B Channel control structure
987  *      skb
988  * return value:
989  *      number of bytes accepted for sending
990  *      (skb->len if ok, 0 if out of buffer space)
991  *      or error code (< 0, eg. -EINVAL)
992  */
993 int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
994 {
995         int len = skb->len;
996         unsigned long flags;
997
998         spin_lock_irqsave(&bcs->cs->lock, flags);
999         if (!bcs->cs->connected) {
1000                 spin_unlock_irqrestore(&bcs->cs->lock, flags);
1001                 return -ENODEV;
1002         }
1003
1004         skb_queue_tail(&bcs->squeue, skb);
1005         gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
1006                 __func__, skb_queue_len(&bcs->squeue));
1007
1008         /* tasklet submits URB if necessary */
1009         tasklet_schedule(&bcs->hw.bas->sent_tasklet);
1010         spin_unlock_irqrestore(&bcs->cs->lock, flags);
1011
1012         return len;     /* ok so far */
1013 }