Blame view

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

9d4bee2b9   Tilman Schmidt   gigaset: atomic c...
945
  		if (cs->mstate == MS_LOCKED) {
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
946
  			gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
01371500b   Tilman Schmidt   [PATCH] isdn4linu...
947
  					   numbytes, src);
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
948
949
  			gigaset_if_receive(inbuf->cs, src, numbytes);
  		} else {
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
950
951
952
953
954
955
  			cmd_loop(src, numbytes, inbuf);
  		}
  
  		head += numbytes;
  		if (head == RBUFSIZE)
  			head = 0;
784d5858a   Tilman Schmidt   [PATCH] isdn4linu...
956
  		gig_dbg(DEBUG_INTR, "setting head to %u", head);
9d4bee2b9   Tilman Schmidt   gigaset: atomic c...
957
  		inbuf->head = head;
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
958
959
960
961
962
  	}
  }
  
  
  /* == data output ========================================================== */
1cec9727f   Tilman Schmidt   gigaset: add kern...
963
964
965
966
967
  /**
   * gigaset_isoc_send_skb() - queue an skb for sending
   * @bcs:	B channel descriptor structure.
   * @skb:	data to send.
   *
088ec0cc9   Tilman Schmidt   gigaset: prepare ...
968
   * Called by LL to queue an skb for sending, and start transmission if
1cec9727f   Tilman Schmidt   gigaset: add kern...
969
   * necessary.
088ec0cc9   Tilman Schmidt   gigaset: prepare ...
970
   * Once the payload data has been transmitted completely, gigaset_skb_sent()
4dd8230ac   Tilman Schmidt   gigaset: fix bad ...
971
   * will be called with the skb's link layer header preserved.
1cec9727f   Tilman Schmidt   gigaset: add kern...
972
973
974
975
   *
   * Return value:
   *	number of bytes accepted for sending (skb->len) if ok,
   *	error code < 0 (eg. -ENODEV) on error
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
976
977
978
   */
  int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb)
  {
d48c77841   Tilman Schmidt   [PATCH] isdn4linu...
979
  	int len = skb->len;
69049cc87   Tilman Schmidt   [PATCH] isdn4linu...
980
  	unsigned long flags;
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
981

73a888145   Tilman Schmidt   [PATCH] isdn4linu...
982
983
984
985
986
  	spin_lock_irqsave(&bcs->cs->lock, flags);
  	if (!bcs->cs->connected) {
  		spin_unlock_irqrestore(&bcs->cs->lock, flags);
  		return -ENODEV;
  	}
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
987
  	skb_queue_tail(&bcs->squeue, skb);
784d5858a   Tilman Schmidt   [PATCH] isdn4linu...
988
989
  	gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d",
  		__func__, skb_queue_len(&bcs->squeue));
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
990
991
  
  	/* tasklet submits URB if necessary */
73a888145   Tilman Schmidt   [PATCH] isdn4linu...
992
  	tasklet_schedule(&bcs->hw.bas->sent_tasklet);
69049cc87   Tilman Schmidt   [PATCH] isdn4linu...
993
  	spin_unlock_irqrestore(&bcs->cs->lock, flags);
76bb4685b   Hansjoerg Lipp   [PATCH] isdn4linu...
994
995
996
  
  	return len;	/* ok so far */
  }