1 /* $Id: netjet.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
2  *
3  * low level stuff for Traverse Technologie NETJet ISDN cards
4  *
5  * Author       Karsten Keil
6  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * Thanks to Traverse Technologies Australia for documents and information
12  *
13  * 16-Apr-2002 - led code added - Guy Ellis (guy@traverse.com.au)
14  *
15  */
16 
17 #define __NO_VERSION__
18 #include <linux/init.h>
19 #include "hisax.h"
20 #include "isac.h"
21 #include "hscx.h"
22 #include "isdnl1.h"
23 #include <linux/pci.h>
24 #include <linux/interrupt.h>
25 #include <linux/ppp_defs.h>
26 #include <asm/io.h>
27 #include "netjet.h"
28 
29 const char *NETjet_revision = "$Revision: 1.1.4.1 $";
30 
31 /* Interface functions */
32 
33 u_char
NETjet_ReadIC(struct IsdnCardState * cs,u_char offset)34 NETjet_ReadIC(struct IsdnCardState *cs, u_char offset)
35 {
36 	long flags;
37 	u_char ret;
38 
39 	save_flags(flags);
40 	cli();
41 	cs->hw.njet.auxd &= 0xfc;
42 	cs->hw.njet.auxd |= (offset>>4) & 3;
43 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
44 	ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2));
45 	restore_flags(flags);
46 	return(ret);
47 }
48 
49 void
NETjet_WriteIC(struct IsdnCardState * cs,u_char offset,u_char value)50 NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value)
51 {
52 	long flags;
53 
54 	save_flags(flags);
55 	cli();
56 	cs->hw.njet.auxd &= 0xfc;
57 	cs->hw.njet.auxd |= (offset>>4) & 3;
58 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
59 	byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value);
60 	restore_flags(flags);
61 }
62 
63 void
NETjet_ReadICfifo(struct IsdnCardState * cs,u_char * data,int size)64 NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size)
65 {
66 	cs->hw.njet.auxd &= 0xfc;
67 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
68 	insb(cs->hw.njet.isac, data, size);
69 }
70 
71 __u16 fcstab[256] =
72 {
73 	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
74 	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
75 	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
76 	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
77 	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
78 	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
79 	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
80 	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
81 	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
82 	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
83 	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
84 	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
85 	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
86 	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
87 	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
88 	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
89 	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
90 	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
91 	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
92 	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
93 	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
94 	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
95 	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
96 	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
97 	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
98 	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
99 	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
100 	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
101 	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
102 	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
103 	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
104 	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
105 };
106 
107 void
NETjet_WriteICfifo(struct IsdnCardState * cs,u_char * data,int size)108 NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size)
109 {
110 	cs->hw.njet.auxd &= 0xfc;
111 	byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
112 	outsb(cs->hw.njet.isac, data, size);
113 }
114 
fill_mem(struct BCState * bcs,u_int * pos,u_int cnt,int chan,u_char fill)115 void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
116 {
117 	u_int mask=0x000000ff, val = 0, *p=pos;
118 	u_int i;
119 
120 	val |= fill;
121 	if (chan) {
122 		val  <<= 8;
123 		mask <<= 8;
124 	}
125 	mask ^= 0xffffffff;
126 	for (i=0; i<cnt; i++) {
127 		*p   &= mask;
128 		*p++ |= val;
129 		if (p > bcs->hw.tiger.s_end)
130 			p = bcs->hw.tiger.send;
131 	}
132 }
133 
134 void
mode_tiger(struct BCState * bcs,int mode,int bc)135 mode_tiger(struct BCState *bcs, int mode, int bc)
136 {
137 	struct IsdnCardState *cs = bcs->cs;
138         u_char led;
139 
140 	if (cs->debug & L1_DEB_HSCX)
141 		debugl1(cs, "Tiger mode %d bchan %d/%d",
142 			mode, bc, bcs->channel);
143 	bcs->mode = mode;
144 	bcs->channel = bc;
145 	switch (mode) {
146 		case (L1_MODE_NULL):
147 			fill_mem(bcs, bcs->hw.tiger.send,
148 				NETJET_DMA_TXSIZE, bc, 0xff);
149 			if (cs->debug & L1_DEB_HSCX)
150 				debugl1(cs, "Tiger stat rec %d/%d send %d",
151 					bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err,
152 					bcs->hw.tiger.s_tot);
153 			if ((cs->bcs[0].mode == L1_MODE_NULL) &&
154 				(cs->bcs[1].mode == L1_MODE_NULL)) {
155 				cs->hw.njet.dmactrl = 0;
156 				byteout(cs->hw.njet.base + NETJET_DMACTRL,
157 					cs->hw.njet.dmactrl);
158 				byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
159 			}
160                         if (cs->typ == ISDN_CTYPE_NETJET_S)
161                         {
162                                 // led off
163                                 led = bc & 0x01;
164                                 led = 0x01 << (6 + led); // convert to mask
165                                 led = ~led;
166                                 cs->hw.njet.auxd &= led;
167                                 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
168                         }
169 			break;
170 		case (L1_MODE_TRANS):
171 			break;
172 		case (L1_MODE_HDLC_56K):
173 		case (L1_MODE_HDLC):
174 			fill_mem(bcs, bcs->hw.tiger.send,
175 				NETJET_DMA_TXSIZE, bc, 0xff);
176 			bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH;
177 			bcs->hw.tiger.r_tot = 0;
178 			bcs->hw.tiger.r_bitcnt = 0;
179 			bcs->hw.tiger.r_one = 0;
180 			bcs->hw.tiger.r_err = 0;
181 			bcs->hw.tiger.s_tot = 0;
182 			if (! cs->hw.njet.dmactrl) {
183 				fill_mem(bcs, bcs->hw.tiger.send,
184 					NETJET_DMA_TXSIZE, !bc, 0xff);
185 				cs->hw.njet.dmactrl = 1;
186 				byteout(cs->hw.njet.base + NETJET_DMACTRL,
187 					cs->hw.njet.dmactrl);
188 				byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f);
189 			/* was 0x3f now 0x0f for TJ300 and TJ320  GE 13/07/00 */
190 			}
191 			bcs->hw.tiger.sendp = bcs->hw.tiger.send;
192 			bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
193 			test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
194                         if (cs->typ == ISDN_CTYPE_NETJET_S)
195                         {
196                                 // led on
197                                 led = bc & 0x01;
198                                 led = 0x01 << (6 + led); // convert to mask
199                                 cs->hw.njet.auxd |= led;
200                                 byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
201                         }
202 			break;
203 	}
204 	if (cs->debug & L1_DEB_HSCX)
205 		debugl1(cs, "tiger: set %x %x %x  %x/%x  pulse=%d",
206 			bytein(cs->hw.njet.base + NETJET_DMACTRL),
207 			bytein(cs->hw.njet.base + NETJET_IRQMASK0),
208 			bytein(cs->hw.njet.base + NETJET_IRQSTAT0),
209 			inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
210 			inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
211 			bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
212 }
213 
printframe(struct IsdnCardState * cs,u_char * buf,int count,char * s)214 static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) {
215 	char tmp[128];
216 	char *t = tmp;
217 	int i=count,j;
218 	u_char *p = buf;
219 
220 	t += sprintf(t, "tiger %s(%4d)", s, count);
221 	while (i>0) {
222 		if (i>16)
223 			j=16;
224 		else
225 			j=i;
226 		QuickHex(t, p, j);
227 		debugl1(cs, tmp);
228 		p += j;
229 		i -= j;
230 		t = tmp;
231 		t += sprintf(t, "tiger %s      ", s);
232 	}
233 }
234 
235 // macro for 64k
236 
237 #define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
238 			bitcnt++;\
239 			s_val >>= 1;\
240 			if (val & 1) {\
241 				s_one++;\
242 				s_val |= 0x80;\
243 			} else {\
244 				s_one = 0;\
245 				s_val &= 0x7f;\
246 			}\
247 			if (bitcnt==8) {\
248 				bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
249 				bitcnt = 0;\
250 			}\
251 			if (s_one == 5) {\
252 				s_val >>= 1;\
253 				s_val &= 0x7f;\
254 				bitcnt++;\
255 				s_one = 0;\
256 			}\
257 			if (bitcnt==8) {\
258 				bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
259 				bitcnt = 0;\
260 			}\
261 			val >>= 1;\
262 		}
263 
make_raw_data(struct BCState * bcs)264 static int make_raw_data(struct BCState *bcs) {
265 // this make_raw is for 64k
266 	register u_int i,s_cnt=0;
267 	register u_char j;
268 	register u_char val;
269 	register u_char s_one = 0;
270 	register u_char s_val = 0;
271 	register u_char bitcnt = 0;
272 	u_int fcs;
273 
274 	if (!bcs->tx_skb) {
275 		debugl1(bcs->cs, "tiger make_raw: NULL skb");
276 		return(1);
277 	}
278 	bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE;
279 	fcs = PPP_INITFCS;
280 	for (i=0; i<bcs->tx_skb->len; i++) {
281 		val = bcs->tx_skb->data[i];
282 		fcs = PPP_FCS (fcs, val);
283 		MAKE_RAW_BYTE;
284 	}
285 	fcs ^= 0xffff;
286 	val = fcs & 0xff;
287 	MAKE_RAW_BYTE;
288 	val = (fcs>>8) & 0xff;
289 	MAKE_RAW_BYTE;
290 	val = HDLC_FLAG_VALUE;
291 	for (j=0; j<8; j++) {
292 		bitcnt++;
293 		s_val >>= 1;
294 		if (val & 1)
295 			s_val |= 0x80;
296 		else
297 			s_val &= 0x7f;
298 		if (bitcnt==8) {
299 			bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
300 			bitcnt = 0;
301 		}
302 		val >>= 1;
303 	}
304 	if (bcs->cs->debug & L1_DEB_HSCX)
305 		debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d",
306 			bcs->tx_skb->len, s_cnt, bitcnt);
307 	if (bitcnt) {
308 		while (8>bitcnt++) {
309 			s_val >>= 1;
310 			s_val |= 0x80;
311 		}
312 		bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
313 		bcs->hw.tiger.sendbuf[s_cnt++] = 0xff;	// NJ<->NJ thoughput bug fix
314 	}
315 	bcs->hw.tiger.sendcnt = s_cnt;
316 	bcs->tx_cnt -= bcs->tx_skb->len;
317 	bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
318 	return(0);
319 }
320 
321 // macro for 56k
322 
323 #define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \
324 			bitcnt++;\
325 			s_val >>= 1;\
326 			if (val & 1) {\
327 				s_one++;\
328 				s_val |= 0x80;\
329 			} else {\
330 				s_one = 0;\
331 				s_val &= 0x7f;\
332 			}\
333 			if (bitcnt==7) {\
334 				s_val >>= 1;\
335 				s_val |= 0x80;\
336 				bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
337 				bitcnt = 0;\
338 			}\
339 			if (s_one == 5) {\
340 				s_val >>= 1;\
341 				s_val &= 0x7f;\
342 				bitcnt++;\
343 				s_one = 0;\
344 			}\
345 			if (bitcnt==7) {\
346 				s_val >>= 1;\
347 				s_val |= 0x80;\
348 				bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\
349 				bitcnt = 0;\
350 			}\
351 			val >>= 1;\
352 		}
353 
make_raw_data_56k(struct BCState * bcs)354 static int make_raw_data_56k(struct BCState *bcs) {
355 // this make_raw is for 56k
356 	register u_int i,s_cnt=0;
357 	register u_char j;
358 	register u_char val;
359 	register u_char s_one = 0;
360 	register u_char s_val = 0;
361 	register u_char bitcnt = 0;
362 	u_int fcs;
363 
364 	if (!bcs->tx_skb) {
365 		debugl1(bcs->cs, "tiger make_raw_56k: NULL skb");
366 		return(1);
367 	}
368 	val = HDLC_FLAG_VALUE;
369 	for (j=0; j<8; j++) {
370 		bitcnt++;
371 		s_val >>= 1;
372 		if (val & 1)
373 			s_val |= 0x80;
374 		else
375 			s_val &= 0x7f;
376 		if (bitcnt==7) {
377 			s_val >>= 1;
378 			s_val |= 0x80;
379 			bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
380 			bitcnt = 0;
381 		}
382 		val >>= 1;
383 	};
384 	fcs = PPP_INITFCS;
385 	for (i=0; i<bcs->tx_skb->len; i++) {
386 		val = bcs->tx_skb->data[i];
387 		fcs = PPP_FCS (fcs, val);
388 		MAKE_RAW_BYTE_56K;
389 	}
390 	fcs ^= 0xffff;
391 	val = fcs & 0xff;
392 	MAKE_RAW_BYTE_56K;
393 	val = (fcs>>8) & 0xff;
394 	MAKE_RAW_BYTE_56K;
395 	val = HDLC_FLAG_VALUE;
396 	for (j=0; j<8; j++) {
397 		bitcnt++;
398 		s_val >>= 1;
399 		if (val & 1)
400 			s_val |= 0x80;
401 		else
402 			s_val &= 0x7f;
403 		if (bitcnt==7) {
404 			s_val >>= 1;
405 			s_val |= 0x80;
406 			bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
407 			bitcnt = 0;
408 		}
409 		val >>= 1;
410 	}
411 	if (bcs->cs->debug & L1_DEB_HSCX)
412 		debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d",
413 			bcs->tx_skb->len, s_cnt, bitcnt);
414 	if (bitcnt) {
415 		while (8>bitcnt++) {
416 			s_val >>= 1;
417 			s_val |= 0x80;
418 		}
419 		bcs->hw.tiger.sendbuf[s_cnt++] = s_val;
420 		bcs->hw.tiger.sendbuf[s_cnt++] = 0xff;	// NJ<->NJ thoughput bug fix
421 	}
422 	bcs->hw.tiger.sendcnt = s_cnt;
423 	bcs->tx_cnt -= bcs->tx_skb->len;
424 	bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf;
425 	return(0);
426 }
427 
got_frame(struct BCState * bcs,int count)428 static void got_frame(struct BCState *bcs, int count) {
429 	struct sk_buff *skb;
430 
431 	if (!(skb = dev_alloc_skb(count)))
432 		printk(KERN_WARNING "TIGER: receive out of memory\n");
433 	else {
434 		memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count);
435 		skb_queue_tail(&bcs->rqueue, skb);
436 	}
437 	bcs->event |= 1 << B_RCVBUFREADY;
438 	queue_task(&bcs->tqueue, &tq_immediate);
439 	mark_bh(IMMEDIATE_BH);
440 
441 	if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME)
442 		printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");
443 }
444 
445 
446 
read_raw(struct BCState * bcs,u_int * buf,int cnt)447 static void read_raw(struct BCState *bcs, u_int *buf, int cnt){
448 	int i;
449 	register u_char j;
450 	register u_char val;
451 	u_int  *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1;
452 	register u_char state = bcs->hw.tiger.r_state;
453 	register u_char r_one = bcs->hw.tiger.r_one;
454 	register u_char r_val = bcs->hw.tiger.r_val;
455 	register u_int bitcnt = bcs->hw.tiger.r_bitcnt;
456 	u_int *p = buf;
457 	int bits;
458 	u_char mask;
459 
460         if (bcs->mode == L1_MODE_HDLC) { // it's 64k
461 		mask = 0xff;
462 		bits = 8;
463 	}
464 	else { // it's 56K
465 		mask = 0x7f;
466 		bits = 7;
467 	};
468 	for (i=0;i<cnt;i++) {
469 		val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff);
470 		p++;
471 		if (p > pend)
472 			p = bcs->hw.tiger.rec;
473 		if ((val & mask) == mask) {
474 			state = HDLC_ZERO_SEARCH;
475 			bcs->hw.tiger.r_tot++;
476 			bitcnt = 0;
477 			r_one = 0;
478 			continue;
479 		}
480 		for (j=0;j<bits;j++) {
481 			if (state == HDLC_ZERO_SEARCH) {
482 				if (val & 1) {
483 					r_one++;
484 				} else {
485 					r_one=0;
486 					state= HDLC_FLAG_SEARCH;
487 					if (bcs->cs->debug & L1_DEB_HSCX)
488 						debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x",
489 							bcs->hw.tiger.r_tot,i,j,val);
490 				}
491 			} else if (state == HDLC_FLAG_SEARCH) {
492 				if (val & 1) {
493 					r_one++;
494 					if (r_one>6) {
495 						state=HDLC_ZERO_SEARCH;
496 					}
497 				} else {
498 					if (r_one==6) {
499 						bitcnt=0;
500 						r_val=0;
501 						state=HDLC_FLAG_FOUND;
502 						if (bcs->cs->debug & L1_DEB_HSCX)
503 							debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x",
504 								bcs->hw.tiger.r_tot,i,j,val);
505 					}
506 					r_one=0;
507 				}
508 			} else if (state ==  HDLC_FLAG_FOUND) {
509 				if (val & 1) {
510 					r_one++;
511 					if (r_one>6) {
512 						state=HDLC_ZERO_SEARCH;
513 					} else {
514 						r_val >>= 1;
515 						r_val |= 0x80;
516 						bitcnt++;
517 					}
518 				} else {
519 					if (r_one==6) {
520 						bitcnt=0;
521 						r_val=0;
522 						r_one=0;
523 						val >>= 1;
524 						continue;
525 					} else if (r_one!=5) {
526 						r_val >>= 1;
527 						r_val &= 0x7f;
528 						bitcnt++;
529 					}
530 					r_one=0;
531 				}
532 				if ((state != HDLC_ZERO_SEARCH) &&
533 					!(bitcnt & 7)) {
534 					state=HDLC_FRAME_FOUND;
535 					bcs->hw.tiger.r_fcs = PPP_INITFCS;
536 					bcs->hw.tiger.rcvbuf[0] = r_val;
537 					bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
538 					if (bcs->cs->debug & L1_DEB_HSCX)
539 						debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x",
540 							bcs->hw.tiger.r_tot,i,j,r_val,val,
541 							bcs->cs->hw.njet.irqstat0);
542 				}
543 			} else if (state ==  HDLC_FRAME_FOUND) {
544 				if (val & 1) {
545 					r_one++;
546 					if (r_one>6) {
547 						state=HDLC_ZERO_SEARCH;
548 						bitcnt=0;
549 					} else {
550 						r_val >>= 1;
551 						r_val |= 0x80;
552 						bitcnt++;
553 					}
554 				} else {
555 					if (r_one==6) {
556 						r_val=0;
557 						r_one=0;
558 						bitcnt++;
559 						if (bitcnt & 7) {
560 							debugl1(bcs->cs, "tiger: frame not byte aligned");
561 							state=HDLC_FLAG_SEARCH;
562 							bcs->hw.tiger.r_err++;
563 #ifdef ERROR_STATISTIC
564 							bcs->err_inv++;
565 #endif
566 						} else {
567 							if (bcs->cs->debug & L1_DEB_HSCX)
568 								debugl1(bcs->cs,"tiger frame end(%d,%d): fcs(%x) i %x",
569 									i,j,bcs->hw.tiger.r_fcs, bcs->cs->hw.njet.irqstat0);
570 							if (bcs->hw.tiger.r_fcs == PPP_GOODFCS) {
571 								got_frame(bcs, (bitcnt>>3)-3);
572 							} else {
573 								if (bcs->cs->debug) {
574 									debugl1(bcs->cs, "tiger FCS error");
575 									printframe(bcs->cs, bcs->hw.tiger.rcvbuf,
576 										(bitcnt>>3)-1, "rec");
577 									bcs->hw.tiger.r_err++;
578 								}
579 #ifdef ERROR_STATISTIC
580 							bcs->err_crc++;
581 #endif
582 							}
583 							state=HDLC_FLAG_FOUND;
584 						}
585 						bitcnt=0;
586 					} else if (r_one==5) {
587 						val >>= 1;
588 						r_one=0;
589 						continue;
590 					} else {
591 						r_val >>= 1;
592 						r_val &= 0x7f;
593 						bitcnt++;
594 					}
595 					r_one=0;
596 				}
597 				if ((state == HDLC_FRAME_FOUND) &&
598 					!(bitcnt & 7)) {
599 					if ((bitcnt>>3)>=HSCX_BUFMAX) {
600 						debugl1(bcs->cs, "tiger: frame too big");
601 						r_val=0;
602 						state=HDLC_FLAG_SEARCH;
603 						bcs->hw.tiger.r_err++;
604 #ifdef ERROR_STATISTIC
605 						bcs->err_inv++;
606 #endif
607 					} else {
608 						bcs->hw.tiger.rcvbuf[(bitcnt>>3)-1] = r_val;
609 						bcs->hw.tiger.r_fcs =
610 							PPP_FCS (bcs->hw.tiger.r_fcs, r_val);
611 					}
612 				}
613 			}
614 			val >>= 1;
615 		}
616 		bcs->hw.tiger.r_tot++;
617 	}
618 	bcs->hw.tiger.r_state = state;
619 	bcs->hw.tiger.r_one = r_one;
620 	bcs->hw.tiger.r_val = r_val;
621 	bcs->hw.tiger.r_bitcnt = bitcnt;
622 }
623 
read_tiger(struct IsdnCardState * cs)624 void read_tiger(struct IsdnCardState *cs) {
625 	u_int *p;
626 	int cnt = NETJET_DMA_RXSIZE/2;
627 
628 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_READ) {
629 		debugl1(cs,"tiger warn read double dma %x/%x",
630 			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
631 #ifdef ERROR_STATISTIC
632 		if (cs->bcs[0].mode)
633 			cs->bcs[0].err_rdo++;
634 		if (cs->bcs[1].mode)
635 			cs->bcs[1].err_rdo++;
636 #endif
637 		return;
638 	} else {
639 		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_READ;
640 		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ);
641 	}
642 	if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ_1)
643 		p = cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1;
644 	else
645 		p = cs->bcs[0].hw.tiger.rec + cnt - 1;
646 	if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
647 		read_raw(cs->bcs, p, cnt);
648 
649 	if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
650 		read_raw(cs->bcs + 1, p, cnt);
651 	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ;
652 }
653 
654 static void write_raw(struct BCState *bcs, u_int *buf, int cnt);
655 
netjet_fill_dma(struct BCState * bcs)656 void netjet_fill_dma(struct BCState *bcs)
657 {
658 	register u_int *p, *sp;
659 	register int cnt;
660 
661 	if (!bcs->tx_skb)
662 		return;
663 	if (bcs->cs->debug & L1_DEB_HSCX)
664 		debugl1(bcs->cs,"tiger fill_dma1: c%d %4x", bcs->channel,
665 			bcs->Flag);
666 	if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag))
667 		return;
668 	if (bcs->mode == L1_MODE_HDLC) { // it's 64k
669 		if (make_raw_data(bcs))
670 			return;
671 	}
672 	else { // it's 56k
673 		if (make_raw_data_56k(bcs))
674 			return;
675 	};
676 	if (bcs->cs->debug & L1_DEB_HSCX)
677 		debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel,
678 			bcs->Flag);
679 	if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
680 		write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
681 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
682 		p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
683 		sp = bcs->hw.tiger.sendp;
684 		if (p == bcs->hw.tiger.s_end)
685 			p = bcs->hw.tiger.send -1;
686 		if (sp == bcs->hw.tiger.s_end)
687 			sp = bcs->hw.tiger.send -1;
688 		cnt = p - sp;
689 		if (cnt <0) {
690 			write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free);
691 		} else {
692 			p++;
693 			cnt++;
694 			if (p > bcs->hw.tiger.s_end)
695 				p = bcs->hw.tiger.send;
696 			p++;
697 			cnt++;
698 			if (p > bcs->hw.tiger.s_end)
699 				p = bcs->hw.tiger.send;
700 			write_raw(bcs, p, bcs->hw.tiger.free - cnt);
701 		}
702 	} else if (test_and_clear_bit(BC_FLG_EMPTY, &bcs->Flag)) {
703 		p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR));
704 		cnt = bcs->hw.tiger.s_end - p;
705 		if (cnt < 2) {
706 			p = bcs->hw.tiger.send + 1;
707 			cnt = NETJET_DMA_TXSIZE/2 - 2;
708 		} else {
709 			p++;
710 			p++;
711 			if (cnt <= (NETJET_DMA_TXSIZE/2))
712 				cnt += NETJET_DMA_TXSIZE/2;
713 			cnt--;
714 			cnt--;
715 		}
716 		write_raw(bcs, p, cnt);
717 	}
718 	if (bcs->cs->debug & L1_DEB_HSCX)
719 		debugl1(bcs->cs,"tiger fill_dma3: c%d %4x", bcs->channel,
720 			bcs->Flag);
721 }
722 
write_raw(struct BCState * bcs,u_int * buf,int cnt)723 static void write_raw(struct BCState *bcs, u_int *buf, int cnt) {
724 	u_int mask, val, *p=buf;
725 	u_int i, s_cnt;
726 
727         if (cnt <= 0)
728         	return;
729 	if (test_bit(BC_FLG_BUSY, &bcs->Flag)) {
730 		if (bcs->hw.tiger.sendcnt> cnt) {
731 			s_cnt = cnt;
732 			bcs->hw.tiger.sendcnt -= cnt;
733 		} else {
734 			s_cnt = bcs->hw.tiger.sendcnt;
735 			bcs->hw.tiger.sendcnt = 0;
736 		}
737 		if (bcs->channel)
738 			mask = 0xffff00ff;
739 		else
740 			mask = 0xffffff00;
741 		for (i=0; i<s_cnt; i++) {
742 			val = bcs->channel ? ((bcs->hw.tiger.sp[i] <<8) & 0xff00) :
743 				(bcs->hw.tiger.sp[i]);
744 			*p   &= mask;
745 			*p++ |= val;
746 			if (p>bcs->hw.tiger.s_end)
747 				p = bcs->hw.tiger.send;
748 		}
749 		bcs->hw.tiger.s_tot += s_cnt;
750 		if (bcs->cs->debug & L1_DEB_HSCX)
751 			debugl1(bcs->cs,"tiger write_raw: c%d %x-%x %d/%d %d %x", bcs->channel,
752 				(u_int)buf, (u_int)p, s_cnt, cnt,
753 				bcs->hw.tiger.sendcnt, bcs->cs->hw.njet.irqstat0);
754 		if (bcs->cs->debug & L1_DEB_HSCX_FIFO)
755 			printframe(bcs->cs, bcs->hw.tiger.sp, s_cnt, "snd");
756 		bcs->hw.tiger.sp += s_cnt;
757 		bcs->hw.tiger.sendp = p;
758 		if (!bcs->hw.tiger.sendcnt) {
759 			if (!bcs->tx_skb) {
760 				debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt);
761 			} else {
762 				if (bcs->st->lli.l1writewakeup &&
763 					(PACKET_NOACK != bcs->tx_skb->pkt_type))
764 					bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
765 				dev_kfree_skb_any(bcs->tx_skb);
766 				bcs->tx_skb = NULL;
767 			}
768 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
769 			bcs->hw.tiger.free = cnt - s_cnt;
770 			if (bcs->hw.tiger.free > (NETJET_DMA_TXSIZE/2))
771 				test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
772 			else {
773 				test_and_clear_bit(BC_FLG_HALF, &bcs->Flag);
774 				test_and_set_bit(BC_FLG_NOFRAME, &bcs->Flag);
775 			}
776 			if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
777 				netjet_fill_dma(bcs);
778 			} else {
779 				mask ^= 0xffffffff;
780 				if (s_cnt < cnt) {
781 					for (i=s_cnt; i<cnt;i++) {
782 						*p++ |= mask;
783 						if (p>bcs->hw.tiger.s_end)
784 							p = bcs->hw.tiger.send;
785 					}
786 					if (bcs->cs->debug & L1_DEB_HSCX)
787 						debugl1(bcs->cs, "tiger write_raw: fill rest %d",
788 							cnt - s_cnt);
789 				}
790 				bcs->event |= 1 << B_XMTBUFREADY;
791 				queue_task(&bcs->tqueue, &tq_immediate);
792 				mark_bh(IMMEDIATE_BH);
793 			}
794 		}
795 	} else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) {
796 		test_and_set_bit(BC_FLG_HALF, &bcs->Flag);
797 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
798 		bcs->hw.tiger.free += cnt;
799 		if (bcs->cs->debug & L1_DEB_HSCX)
800 			debugl1(bcs->cs,"tiger write_raw: fill half");
801 	} else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) {
802 		test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
803 		fill_mem(bcs, buf, cnt, bcs->channel, 0xff);
804 		if (bcs->cs->debug & L1_DEB_HSCX)
805 			debugl1(bcs->cs,"tiger write_raw: fill full");
806 	}
807 }
808 
write_tiger(struct IsdnCardState * cs)809 void write_tiger(struct IsdnCardState *cs) {
810 	u_int *p, cnt = NETJET_DMA_TXSIZE/2;
811 
812 	if ((cs->hw.njet.irqstat0 & cs->hw.njet.last_is0) & NETJET_IRQM0_WRITE) {
813 		debugl1(cs,"tiger warn write double dma %x/%x",
814 			cs->hw.njet.irqstat0, cs->hw.njet.last_is0);
815 #ifdef ERROR_STATISTIC
816 		if (cs->bcs[0].mode)
817 			cs->bcs[0].err_tx++;
818 		if (cs->bcs[1].mode)
819 			cs->bcs[1].err_tx++;
820 #endif
821 		return;
822 	} else {
823 		cs->hw.njet.last_is0 &= ~NETJET_IRQM0_WRITE;
824 		cs->hw.njet.last_is0 |= (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE);
825 	}
826 	if (cs->hw.njet.irqstat0  & NETJET_IRQM0_WRITE_1)
827 		p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
828 	else
829 		p = cs->bcs[0].hw.tiger.send + cnt - 1;
830 	if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K))
831 		write_raw(cs->bcs, p, cnt);
832 	if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K))
833 		write_raw(cs->bcs + 1, p, cnt);
834 	cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE;
835 }
836 
837 static void
tiger_l2l1(struct PStack * st,int pr,void * arg)838 tiger_l2l1(struct PStack *st, int pr, void *arg)
839 {
840 	struct sk_buff *skb = arg;
841 	long flags;
842 
843 	switch (pr) {
844 		case (PH_DATA | REQUEST):
845 			save_flags(flags);
846 			cli();
847 			if (st->l1.bcs->tx_skb) {
848 				skb_queue_tail(&st->l1.bcs->squeue, skb);
849 				restore_flags(flags);
850 			} else {
851 				st->l1.bcs->tx_skb = skb;
852 				st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
853 				restore_flags(flags);
854 			}
855 			break;
856 		case (PH_PULL | INDICATION):
857 			if (st->l1.bcs->tx_skb) {
858 				printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n");
859 				break;
860 			}
861 			save_flags(flags);
862 			cli();
863 			st->l1.bcs->tx_skb = skb;
864 			st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
865 			restore_flags(flags);
866 			break;
867 		case (PH_PULL | REQUEST):
868 			if (!st->l1.bcs->tx_skb) {
869 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
870 				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
871 			} else
872 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
873 			break;
874 		case (PH_ACTIVATE | REQUEST):
875 			test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
876 			mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
877 			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
878 			st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
879 			l1_msg_b(st, pr, arg);
880 			break;
881 		case (PH_DEACTIVATE | REQUEST):
882 			/* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
883 			st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
884 			l1_msg_b(st, pr, arg);
885 			break;
886 		case (PH_DEACTIVATE | CONFIRM):
887 			test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
888 			test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
889 			mode_tiger(st->l1.bcs, 0, st->l1.bc);
890 			st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
891 			break;
892 	}
893 }
894 
895 
896 void
close_tigerstate(struct BCState * bcs)897 close_tigerstate(struct BCState *bcs)
898 {
899 	mode_tiger(bcs, 0, bcs->channel);
900 	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
901 		if (bcs->hw.tiger.rcvbuf) {
902 			kfree(bcs->hw.tiger.rcvbuf);
903 			bcs->hw.tiger.rcvbuf = NULL;
904 		}
905 		if (bcs->hw.tiger.sendbuf) {
906 			kfree(bcs->hw.tiger.sendbuf);
907 			bcs->hw.tiger.sendbuf = NULL;
908 		}
909 		skb_queue_purge(&bcs->rqueue);
910 		skb_queue_purge(&bcs->squeue);
911 		if (bcs->tx_skb) {
912 			dev_kfree_skb_any(bcs->tx_skb);
913 			bcs->tx_skb = NULL;
914 			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
915 		}
916 	}
917 }
918 
919 static int
open_tigerstate(struct IsdnCardState * cs,struct BCState * bcs)920 open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
921 {
922 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
923 		if (!(bcs->hw.tiger.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
924 			printk(KERN_WARNING
925 			       "HiSax: No memory for tiger.rcvbuf\n");
926 			return (1);
927 		}
928 		if (!(bcs->hw.tiger.sendbuf = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
929 			printk(KERN_WARNING
930 			       "HiSax: No memory for tiger.sendbuf\n");
931 			return (1);
932 		}
933 		skb_queue_head_init(&bcs->rqueue);
934 		skb_queue_head_init(&bcs->squeue);
935 	}
936 	bcs->tx_skb = NULL;
937 	bcs->hw.tiger.sendcnt = 0;
938 	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
939 	bcs->event = 0;
940 	bcs->tx_cnt = 0;
941 	return (0);
942 }
943 
944 int
setstack_tiger(struct PStack * st,struct BCState * bcs)945 setstack_tiger(struct PStack *st, struct BCState *bcs)
946 {
947 	bcs->channel = st->l1.bc;
948 	if (open_tigerstate(st->l1.hardware, bcs))
949 		return (-1);
950 	st->l1.bcs = bcs;
951 	st->l2.l2l1 = tiger_l2l1;
952 	setstack_manager(st);
953 	bcs->st = st;
954 	setstack_l1_B(st);
955 	return (0);
956 }
957 
958 
959 void __init
inittiger(struct IsdnCardState * cs)960 inittiger(struct IsdnCardState *cs)
961 {
962 	if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
963 		GFP_KERNEL | GFP_DMA))) {
964 		printk(KERN_WARNING
965 		       "HiSax: No memory for tiger.send\n");
966 		return;
967 	}
968 	cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1;
969 	cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1;
970 	cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send;
971 	cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq;
972 	cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end;
973 
974 	memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int));
975 	debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send,
976 		(u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1));
977 	outl(virt_to_bus(cs->bcs[0].hw.tiger.send),
978 		cs->hw.njet.base + NETJET_DMA_READ_START);
979 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq),
980 		cs->hw.njet.base + NETJET_DMA_READ_IRQ);
981 	outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end),
982 		cs->hw.njet.base + NETJET_DMA_READ_END);
983 	if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int),
984 		GFP_KERNEL | GFP_DMA))) {
985 		printk(KERN_WARNING
986 		       "HiSax: No memory for tiger.rec\n");
987 		return;
988 	}
989 	debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec,
990 		(u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1));
991 	cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec;
992 	memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int));
993 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec),
994 		cs->hw.njet.base + NETJET_DMA_WRITE_START);
995 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1),
996 		cs->hw.njet.base + NETJET_DMA_WRITE_IRQ);
997 	outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1),
998 		cs->hw.njet.base + NETJET_DMA_WRITE_END);
999 	debugl1(cs, "tiger: dmacfg  %x/%x  pulse=%d",
1000 		inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR),
1001 		inl(cs->hw.njet.base + NETJET_DMA_READ_ADR),
1002 		bytein(cs->hw.njet.base + NETJET_PULSE_CNT));
1003 	cs->hw.njet.last_is0 = 0;
1004 	cs->bcs[0].BC_SetStack = setstack_tiger;
1005 	cs->bcs[1].BC_SetStack = setstack_tiger;
1006 	cs->bcs[0].BC_Close = close_tigerstate;
1007 	cs->bcs[1].BC_Close = close_tigerstate;
1008 }
1009 
1010 void
releasetiger(struct IsdnCardState * cs)1011 releasetiger(struct IsdnCardState *cs)
1012 {
1013 	if (cs->bcs[0].hw.tiger.send) {
1014 		kfree(cs->bcs[0].hw.tiger.send);
1015 		cs->bcs[0].hw.tiger.send = NULL;
1016 	}
1017 	if (cs->bcs[1].hw.tiger.send) {
1018 		cs->bcs[1].hw.tiger.send = NULL;
1019 	}
1020 	if (cs->bcs[0].hw.tiger.rec) {
1021 		kfree(cs->bcs[0].hw.tiger.rec);
1022 		cs->bcs[0].hw.tiger.rec = NULL;
1023 	}
1024 	if (cs->bcs[1].hw.tiger.rec) {
1025 		cs->bcs[1].hw.tiger.rec = NULL;
1026 	}
1027 }
1028 
1029 void
release_io_netjet(struct IsdnCardState * cs)1030 release_io_netjet(struct IsdnCardState *cs)
1031 {
1032 	byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
1033 	byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0);
1034 	releasetiger(cs);
1035 	release_region(cs->hw.njet.base, 256);
1036 }
1037 
1038