• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $
2  *
3  * ICC specific routines
4  *
5  * Author       Matt Henderson & Guy Ellis
6  * Copyright    by Traverse Technologies Pty Ltd, www.travers.com.au
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  * 1999.6.25 Initial implementation of routines for Siemens ISDN
12  * Communication Controller PEB 2070 based on the ISAC routines
13  * written by Karsten Keil.
14  *
15  */
16 
17 #include <linux/init.h>
18 #include "hisax.h"
19 #include "icc.h"
20 // #include "arcofi.h"
21 #include "isdnl1.h"
22 #include <linux/interrupt.h>
23 
24 #define DBUSY_TIMER_VALUE 80
25 #define ARCOFI_USE 0
26 
27 static char *ICCVer[] =
28 {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"};
29 
30 void
ICCVersion(struct IsdnCardState * cs,char * s)31 ICCVersion(struct IsdnCardState *cs, char *s)
32 {
33 	int val;
34 
35 	val = cs->readisac(cs, ICC_RBCH);
36 	printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]);
37 }
38 
39 static void
ph_command(struct IsdnCardState * cs,unsigned int command)40 ph_command(struct IsdnCardState *cs, unsigned int command)
41 {
42 	if (cs->debug & L1_DEB_ISAC)
43 		debugl1(cs, "ph_command %x", command);
44 	cs->writeisac(cs, ICC_CIX0, (command << 2) | 3);
45 }
46 
47 
48 static void
icc_new_ph(struct IsdnCardState * cs)49 icc_new_ph(struct IsdnCardState *cs)
50 {
51 	switch (cs->dc.icc.ph_state) {
52 		case (ICC_IND_EI1):
53 			ph_command(cs, ICC_CMD_DI);
54 			l1_msg(cs, HW_RESET | INDICATION, NULL);
55 			break;
56 		case (ICC_IND_DC):
57 			l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
58 			break;
59 		case (ICC_IND_DR):
60 			l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
61 			break;
62 		case (ICC_IND_PU):
63 			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
64 			break;
65 		case (ICC_IND_FJ):
66 			l1_msg(cs, HW_RSYNC | INDICATION, NULL);
67 			break;
68 		case (ICC_IND_AR):
69 			l1_msg(cs, HW_INFO2 | INDICATION, NULL);
70 			break;
71 		case (ICC_IND_AI):
72 			l1_msg(cs, HW_INFO4 | INDICATION, NULL);
73 			break;
74 		default:
75 			break;
76 	}
77 }
78 
79 static void
icc_bh(struct work_struct * work)80 icc_bh(struct work_struct *work)
81 {
82 	struct IsdnCardState *cs =
83 		container_of(work, struct IsdnCardState, tqueue);
84 	struct PStack *stptr;
85 
86 	if (!cs)
87 		return;
88 	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
89 		if (cs->debug)
90 			debugl1(cs, "D-Channel Busy cleared");
91 		stptr = cs->stlist;
92 		while (stptr != NULL) {
93 			stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
94 			stptr = stptr->next;
95 		}
96 	}
97 	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event))
98 		icc_new_ph(cs);
99 	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
100 		DChannel_proc_rcv(cs);
101 	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
102 		DChannel_proc_xmt(cs);
103 #if ARCOFI_USE
104 	if (!test_bit(HW_ARCOFI, &cs->HW_Flags))
105 		return;
106 	if (test_and_clear_bit(D_RX_MON1, &cs->event))
107 		arcofi_fsm(cs, ARCOFI_RX_END, NULL);
108 	if (test_and_clear_bit(D_TX_MON1, &cs->event))
109 		arcofi_fsm(cs, ARCOFI_TX_END, NULL);
110 #endif
111 }
112 
113 static void
icc_empty_fifo(struct IsdnCardState * cs,int count)114 icc_empty_fifo(struct IsdnCardState *cs, int count)
115 {
116 	u_char *ptr;
117 
118 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
119 		debugl1(cs, "icc_empty_fifo");
120 
121 	if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
122 		if (cs->debug & L1_DEB_WARN)
123 			debugl1(cs, "icc_empty_fifo overrun %d",
124 				cs->rcvidx + count);
125 		cs->writeisac(cs, ICC_CMDR, 0x80);
126 		cs->rcvidx = 0;
127 		return;
128 	}
129 	ptr = cs->rcvbuf + cs->rcvidx;
130 	cs->rcvidx += count;
131 	cs->readisacfifo(cs, ptr, count);
132 	cs->writeisac(cs, ICC_CMDR, 0x80);
133 	if (cs->debug & L1_DEB_ISAC_FIFO) {
134 		char *t = cs->dlog;
135 
136 		t += sprintf(t, "icc_empty_fifo cnt %d", count);
137 		QuickHex(t, ptr, count);
138 		debugl1(cs, cs->dlog);
139 	}
140 }
141 
142 static void
icc_fill_fifo(struct IsdnCardState * cs)143 icc_fill_fifo(struct IsdnCardState *cs)
144 {
145 	int count, more;
146 	u_char *ptr;
147 
148 	if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO))
149 		debugl1(cs, "icc_fill_fifo");
150 
151 	if (!cs->tx_skb)
152 		return;
153 
154 	count = cs->tx_skb->len;
155 	if (count <= 0)
156 		return;
157 
158 	more = 0;
159 	if (count > 32) {
160 		more = !0;
161 		count = 32;
162 	}
163 	ptr = cs->tx_skb->data;
164 	skb_pull(cs->tx_skb, count);
165 	cs->tx_cnt += count;
166 	cs->writeisacfifo(cs, ptr, count);
167 	cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa);
168 	if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
169 		debugl1(cs, "icc_fill_fifo dbusytimer running");
170 		del_timer(&cs->dbusytimer);
171 	}
172 	init_timer(&cs->dbusytimer);
173 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
174 	add_timer(&cs->dbusytimer);
175 	if (cs->debug & L1_DEB_ISAC_FIFO) {
176 		char *t = cs->dlog;
177 
178 		t += sprintf(t, "icc_fill_fifo cnt %d", count);
179 		QuickHex(t, ptr, count);
180 		debugl1(cs, cs->dlog);
181 	}
182 }
183 
184 void
icc_interrupt(struct IsdnCardState * cs,u_char val)185 icc_interrupt(struct IsdnCardState *cs, u_char val)
186 {
187 	u_char exval, v1;
188 	struct sk_buff *skb;
189 	unsigned int count;
190 
191 	if (cs->debug & L1_DEB_ISAC)
192 		debugl1(cs, "ICC interrupt %x", val);
193 	if (val & 0x80) {	/* RME */
194 		exval = cs->readisac(cs, ICC_RSTA);
195 		if ((exval & 0x70) != 0x20) {
196 			if (exval & 0x40) {
197 				if (cs->debug & L1_DEB_WARN)
198 					debugl1(cs, "ICC RDO");
199 #ifdef ERROR_STATISTIC
200 				cs->err_rx++;
201 #endif
202 			}
203 			if (!(exval & 0x20)) {
204 				if (cs->debug & L1_DEB_WARN)
205 					debugl1(cs, "ICC CRC error");
206 #ifdef ERROR_STATISTIC
207 				cs->err_crc++;
208 #endif
209 			}
210 			cs->writeisac(cs, ICC_CMDR, 0x80);
211 		} else {
212 			count = cs->readisac(cs, ICC_RBCL) & 0x1f;
213 			if (count == 0)
214 				count = 32;
215 			icc_empty_fifo(cs, count);
216 			if ((count = cs->rcvidx) > 0) {
217 				cs->rcvidx = 0;
218 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
219 					printk(KERN_WARNING "HiSax: D receive out of memory\n");
220 				else {
221 					memcpy(skb_put(skb, count), cs->rcvbuf, count);
222 					skb_queue_tail(&cs->rq, skb);
223 				}
224 			}
225 		}
226 		cs->rcvidx = 0;
227 		schedule_event(cs, D_RCVBUFREADY);
228 	}
229 	if (val & 0x40) {	/* RPF */
230 		icc_empty_fifo(cs, 32);
231 	}
232 	if (val & 0x20) {	/* RSC */
233 		/* never */
234 		if (cs->debug & L1_DEB_WARN)
235 			debugl1(cs, "ICC RSC interrupt");
236 	}
237 	if (val & 0x10) {	/* XPR */
238 		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
239 			del_timer(&cs->dbusytimer);
240 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
241 			schedule_event(cs, D_CLEARBUSY);
242 		if (cs->tx_skb) {
243 			if (cs->tx_skb->len) {
244 				icc_fill_fifo(cs);
245 				goto afterXPR;
246 			} else {
247 				dev_kfree_skb_irq(cs->tx_skb);
248 				cs->tx_cnt = 0;
249 				cs->tx_skb = NULL;
250 			}
251 		}
252 		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
253 			cs->tx_cnt = 0;
254 			icc_fill_fifo(cs);
255 		} else
256 			schedule_event(cs, D_XMTBUFREADY);
257 	}
258       afterXPR:
259 	if (val & 0x04) {	/* CISQ */
260 		exval = cs->readisac(cs, ICC_CIR0);
261 		if (cs->debug & L1_DEB_ISAC)
262 			debugl1(cs, "ICC CIR0 %02X", exval );
263 		if (exval & 2) {
264 			cs->dc.icc.ph_state = (exval >> 2) & 0xf;
265 			if (cs->debug & L1_DEB_ISAC)
266 				debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state);
267 			schedule_event(cs, D_L1STATECHANGE);
268 		}
269 		if (exval & 1) {
270 			exval = cs->readisac(cs, ICC_CIR1);
271 			if (cs->debug & L1_DEB_ISAC)
272 				debugl1(cs, "ICC CIR1 %02X", exval );
273 		}
274 	}
275 	if (val & 0x02) {	/* SIN */
276 		/* never */
277 		if (cs->debug & L1_DEB_WARN)
278 			debugl1(cs, "ICC SIN interrupt");
279 	}
280 	if (val & 0x01) {	/* EXI */
281 		exval = cs->readisac(cs, ICC_EXIR);
282 		if (cs->debug & L1_DEB_WARN)
283 			debugl1(cs, "ICC EXIR %02x", exval);
284 		if (exval & 0x80) {  /* XMR */
285 			debugl1(cs, "ICC XMR");
286 			printk(KERN_WARNING "HiSax: ICC XMR\n");
287 		}
288 		if (exval & 0x40) {  /* XDU */
289 			debugl1(cs, "ICC XDU");
290 			printk(KERN_WARNING "HiSax: ICC XDU\n");
291 #ifdef ERROR_STATISTIC
292 			cs->err_tx++;
293 #endif
294 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
295 				del_timer(&cs->dbusytimer);
296 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
297 				schedule_event(cs, D_CLEARBUSY);
298 			if (cs->tx_skb) { /* Restart frame */
299 				skb_push(cs->tx_skb, cs->tx_cnt);
300 				cs->tx_cnt = 0;
301 				icc_fill_fifo(cs);
302 			} else {
303 				printk(KERN_WARNING "HiSax: ICC XDU no skb\n");
304 				debugl1(cs, "ICC XDU no skb");
305 			}
306 		}
307 		if (exval & 0x04) {  /* MOS */
308 			v1 = cs->readisac(cs, ICC_MOSR);
309 			if (cs->debug & L1_DEB_MONITOR)
310 				debugl1(cs, "ICC MOSR %02x", v1);
311 #if ARCOFI_USE
312 			if (v1 & 0x08) {
313 				if (!cs->dc.icc.mon_rx) {
314 					if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
315 						if (cs->debug & L1_DEB_WARN)
316 							debugl1(cs, "ICC MON RX out of memory!");
317 						cs->dc.icc.mocr &= 0xf0;
318 						cs->dc.icc.mocr |= 0x0a;
319 						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
320 						goto afterMONR0;
321 					} else
322 						cs->dc.icc.mon_rxp = 0;
323 				}
324 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
325 					cs->dc.icc.mocr &= 0xf0;
326 					cs->dc.icc.mocr |= 0x0a;
327 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
328 					cs->dc.icc.mon_rxp = 0;
329 					if (cs->debug & L1_DEB_WARN)
330 						debugl1(cs, "ICC MON RX overflow!");
331 					goto afterMONR0;
332 				}
333 				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0);
334 				if (cs->debug & L1_DEB_MONITOR)
335 					debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
336 				if (cs->dc.icc.mon_rxp == 1) {
337 					cs->dc.icc.mocr |= 0x04;
338 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
339 				}
340 			}
341 		      afterMONR0:
342 			if (v1 & 0x80) {
343 				if (!cs->dc.icc.mon_rx) {
344 					if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
345 						if (cs->debug & L1_DEB_WARN)
346 							debugl1(cs, "ICC MON RX out of memory!");
347 						cs->dc.icc.mocr &= 0x0f;
348 						cs->dc.icc.mocr |= 0xa0;
349 						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
350 						goto afterMONR1;
351 					} else
352 						cs->dc.icc.mon_rxp = 0;
353 				}
354 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
355 					cs->dc.icc.mocr &= 0x0f;
356 					cs->dc.icc.mocr |= 0xa0;
357 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
358 					cs->dc.icc.mon_rxp = 0;
359 					if (cs->debug & L1_DEB_WARN)
360 						debugl1(cs, "ICC MON RX overflow!");
361 					goto afterMONR1;
362 				}
363 				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1);
364 				if (cs->debug & L1_DEB_MONITOR)
365 					debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]);
366 				cs->dc.icc.mocr |= 0x40;
367 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
368 			}
369 		      afterMONR1:
370 			if (v1 & 0x04) {
371 				cs->dc.icc.mocr &= 0xf0;
372 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
373 				cs->dc.icc.mocr |= 0x0a;
374 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
375 				schedule_event(cs, D_RX_MON0);
376 			}
377 			if (v1 & 0x40) {
378 				cs->dc.icc.mocr &= 0x0f;
379 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
380 				cs->dc.icc.mocr |= 0xa0;
381 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
382 				schedule_event(cs, D_RX_MON1);
383 			}
384 			if (v1 & 0x02) {
385 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
386 					(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
387 					!(v1 & 0x08))) {
388 					cs->dc.icc.mocr &= 0xf0;
389 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
390 					cs->dc.icc.mocr |= 0x0a;
391 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
392 					if (cs->dc.icc.mon_txc &&
393 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
394 						schedule_event(cs, D_TX_MON0);
395 					goto AfterMOX0;
396 				}
397 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
398 					schedule_event(cs, D_TX_MON0);
399 					goto AfterMOX0;
400 				}
401 				cs->writeisac(cs, ICC_MOX0,
402 					cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
403 				if (cs->debug & L1_DEB_MONITOR)
404 					debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
405 			}
406 		      AfterMOX0:
407 			if (v1 & 0x20) {
408 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
409 					(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
410 					!(v1 & 0x80))) {
411 					cs->dc.icc.mocr &= 0x0f;
412 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
413 					cs->dc.icc.mocr |= 0xa0;
414 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
415 					if (cs->dc.icc.mon_txc &&
416 						(cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
417 						schedule_event(cs, D_TX_MON1);
418 					goto AfterMOX1;
419 				}
420 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
421 					schedule_event(cs, D_TX_MON1);
422 					goto AfterMOX1;
423 				}
424 				cs->writeisac(cs, ICC_MOX1,
425 					cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
426 				if (cs->debug & L1_DEB_MONITOR)
427 					debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]);
428 			}
429 		      AfterMOX1:
430 #endif
431 		}
432 	}
433 }
434 
435 static void
ICC_l1hw(struct PStack * st,int pr,void * arg)436 ICC_l1hw(struct PStack *st, int pr, void *arg)
437 {
438 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
439 	struct sk_buff *skb = arg;
440 	u_long flags;
441 	int  val;
442 
443 	switch (pr) {
444 		case (PH_DATA |REQUEST):
445 			if (cs->debug & DEB_DLOG_HEX)
446 				LogFrame(cs, skb->data, skb->len);
447 			if (cs->debug & DEB_DLOG_VERBOSE)
448 				dlogframe(cs, skb, 0);
449 			spin_lock_irqsave(&cs->lock, flags);
450 			if (cs->tx_skb) {
451 				skb_queue_tail(&cs->sq, skb);
452 #ifdef L2FRAME_DEBUG		/* psa */
453 				if (cs->debug & L1_DEB_LAPD)
454 					Logl2Frame(cs, skb, "PH_DATA Queued", 0);
455 #endif
456 			} else {
457 				cs->tx_skb = skb;
458 				cs->tx_cnt = 0;
459 #ifdef L2FRAME_DEBUG		/* psa */
460 				if (cs->debug & L1_DEB_LAPD)
461 					Logl2Frame(cs, skb, "PH_DATA", 0);
462 #endif
463 				icc_fill_fifo(cs);
464 			}
465 			spin_unlock_irqrestore(&cs->lock, flags);
466 			break;
467 		case (PH_PULL |INDICATION):
468 			spin_lock_irqsave(&cs->lock, flags);
469 			if (cs->tx_skb) {
470 				if (cs->debug & L1_DEB_WARN)
471 					debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
472 				skb_queue_tail(&cs->sq, skb);
473 				break;
474 			}
475 			if (cs->debug & DEB_DLOG_HEX)
476 				LogFrame(cs, skb->data, skb->len);
477 			if (cs->debug & DEB_DLOG_VERBOSE)
478 				dlogframe(cs, skb, 0);
479 			cs->tx_skb = skb;
480 			cs->tx_cnt = 0;
481 #ifdef L2FRAME_DEBUG		/* psa */
482 			if (cs->debug & L1_DEB_LAPD)
483 				Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
484 #endif
485 			icc_fill_fifo(cs);
486 			spin_unlock_irqrestore(&cs->lock, flags);
487 			break;
488 		case (PH_PULL | REQUEST):
489 #ifdef L2FRAME_DEBUG		/* psa */
490 			if (cs->debug & L1_DEB_LAPD)
491 				debugl1(cs, "-> PH_REQUEST_PULL");
492 #endif
493 			if (!cs->tx_skb) {
494 				test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
495 				st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
496 			} else
497 				test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
498 			break;
499 		case (HW_RESET | REQUEST):
500 			spin_lock_irqsave(&cs->lock, flags);
501 			if ((cs->dc.icc.ph_state == ICC_IND_EI1) ||
502 				(cs->dc.icc.ph_state == ICC_IND_DR))
503 			        ph_command(cs, ICC_CMD_DI);
504 			else
505 				ph_command(cs, ICC_CMD_RES);
506 			spin_unlock_irqrestore(&cs->lock, flags);
507 			break;
508 		case (HW_ENABLE | REQUEST):
509 			spin_lock_irqsave(&cs->lock, flags);
510 			ph_command(cs, ICC_CMD_DI);
511 			spin_unlock_irqrestore(&cs->lock, flags);
512 			break;
513 		case (HW_INFO1 | REQUEST):
514 			spin_lock_irqsave(&cs->lock, flags);
515 			ph_command(cs, ICC_CMD_AR);
516 			spin_unlock_irqrestore(&cs->lock, flags);
517 			break;
518 		case (HW_INFO3 | REQUEST):
519 			spin_lock_irqsave(&cs->lock, flags);
520 			ph_command(cs, ICC_CMD_AI);
521 			spin_unlock_irqrestore(&cs->lock, flags);
522 			break;
523 		case (HW_TESTLOOP | REQUEST):
524 			spin_lock_irqsave(&cs->lock, flags);
525 			val = 0;
526 			if (1 & (long) arg)
527 				val |= 0x0c;
528 			if (2 & (long) arg)
529 				val |= 0x3;
530 			if (test_bit(HW_IOM1, &cs->HW_Flags)) {
531 				/* IOM 1 Mode */
532 				if (!val) {
533 					cs->writeisac(cs, ICC_SPCR, 0xa);
534 					cs->writeisac(cs, ICC_ADF1, 0x2);
535 				} else {
536 					cs->writeisac(cs, ICC_SPCR, val);
537 					cs->writeisac(cs, ICC_ADF1, 0xa);
538 				}
539 			} else {
540 				/* IOM 2 Mode */
541 				cs->writeisac(cs, ICC_SPCR, val);
542 				if (val)
543 					cs->writeisac(cs, ICC_ADF1, 0x8);
544 				else
545 					cs->writeisac(cs, ICC_ADF1, 0x0);
546 			}
547 			spin_unlock_irqrestore(&cs->lock, flags);
548 			break;
549 		case (HW_DEACTIVATE | RESPONSE):
550 			skb_queue_purge(&cs->rq);
551 			skb_queue_purge(&cs->sq);
552 			if (cs->tx_skb) {
553 				dev_kfree_skb_any(cs->tx_skb);
554 				cs->tx_skb = NULL;
555 			}
556 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
557 				del_timer(&cs->dbusytimer);
558 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
559 				schedule_event(cs, D_CLEARBUSY);
560 			break;
561 		default:
562 			if (cs->debug & L1_DEB_WARN)
563 				debugl1(cs, "icc_l1hw unknown %04x", pr);
564 			break;
565 	}
566 }
567 
568 static void
setstack_icc(struct PStack * st,struct IsdnCardState * cs)569 setstack_icc(struct PStack *st, struct IsdnCardState *cs)
570 {
571 	st->l1.l1hw = ICC_l1hw;
572 }
573 
574 static void
DC_Close_icc(struct IsdnCardState * cs)575 DC_Close_icc(struct IsdnCardState *cs) {
576 	kfree(cs->dc.icc.mon_rx);
577 	cs->dc.icc.mon_rx = NULL;
578 	kfree(cs->dc.icc.mon_tx);
579 	cs->dc.icc.mon_tx = NULL;
580 }
581 
582 static void
dbusy_timer_handler(struct IsdnCardState * cs)583 dbusy_timer_handler(struct IsdnCardState *cs)
584 {
585 	struct PStack *stptr;
586 	int	rbch, star;
587 
588 	if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
589 		rbch = cs->readisac(cs, ICC_RBCH);
590 		star = cs->readisac(cs, ICC_STAR);
591 		if (cs->debug)
592 			debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x",
593 				rbch, star);
594 		if (rbch & ICC_RBCH_XAC) { /* D-Channel Busy */
595 			test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
596 			stptr = cs->stlist;
597 			while (stptr != NULL) {
598 				stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
599 				stptr = stptr->next;
600 			}
601 		} else {
602 			/* discard frame; reset transceiver */
603 			test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags);
604 			if (cs->tx_skb) {
605 				dev_kfree_skb_any(cs->tx_skb);
606 				cs->tx_cnt = 0;
607 				cs->tx_skb = NULL;
608 			} else {
609 				printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n");
610 				debugl1(cs, "D-Channel Busy no skb");
611 			}
612 			cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */
613 			cs->irq_func(cs->irq, cs);
614 		}
615 	}
616 }
617 
618 void
initicc(struct IsdnCardState * cs)619 initicc(struct IsdnCardState *cs)
620 {
621 	cs->setstack_d = setstack_icc;
622 	cs->DC_Close = DC_Close_icc;
623 	cs->dc.icc.mon_tx = NULL;
624 	cs->dc.icc.mon_rx = NULL;
625   	cs->writeisac(cs, ICC_MASK, 0xff);
626   	cs->dc.icc.mocr = 0xaa;
627 	if (test_bit(HW_IOM1, &cs->HW_Flags)) {
628 		/* IOM 1 Mode */
629 		cs->writeisac(cs, ICC_ADF2, 0x0);
630 		cs->writeisac(cs, ICC_SPCR, 0xa);
631 		cs->writeisac(cs, ICC_ADF1, 0x2);
632 		cs->writeisac(cs, ICC_STCR, 0x70);
633 		cs->writeisac(cs, ICC_MODE, 0xc9);
634 	} else {
635 		/* IOM 2 Mode */
636 		if (!cs->dc.icc.adf2)
637 			cs->dc.icc.adf2 = 0x80;
638 		cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2);
639 		cs->writeisac(cs, ICC_SQXR, 0xa0);
640 		cs->writeisac(cs, ICC_SPCR, 0x20);
641 		cs->writeisac(cs, ICC_STCR, 0x70);
642 		cs->writeisac(cs, ICC_MODE, 0xca);
643 		cs->writeisac(cs, ICC_TIMR, 0x00);
644 		cs->writeisac(cs, ICC_ADF1, 0x20);
645 	}
646 	ph_command(cs, ICC_CMD_RES);
647 	cs->writeisac(cs, ICC_MASK, 0x0);
648 	ph_command(cs, ICC_CMD_DI);
649 }
650 
651 void
clear_pending_icc_ints(struct IsdnCardState * cs)652 clear_pending_icc_ints(struct IsdnCardState *cs)
653 {
654 	int val, eval;
655 
656 	val = cs->readisac(cs, ICC_STAR);
657 	debugl1(cs, "ICC STAR %x", val);
658 	val = cs->readisac(cs, ICC_MODE);
659 	debugl1(cs, "ICC MODE %x", val);
660 	val = cs->readisac(cs, ICC_ADF2);
661 	debugl1(cs, "ICC ADF2 %x", val);
662 	val = cs->readisac(cs, ICC_ISTA);
663 	debugl1(cs, "ICC ISTA %x", val);
664 	if (val & 0x01) {
665 		eval = cs->readisac(cs, ICC_EXIR);
666 		debugl1(cs, "ICC EXIR %x", eval);
667 	}
668 	val = cs->readisac(cs, ICC_CIR0);
669 	debugl1(cs, "ICC CIR0 %x", val);
670 	cs->dc.icc.ph_state = (val >> 2) & 0xf;
671 	schedule_event(cs, D_L1STATECHANGE);
672 	/* Disable all IRQ */
673 	cs->writeisac(cs, ICC_MASK, 0xFF);
674 }
675 
676 void __devinit
setup_icc(struct IsdnCardState * cs)677 setup_icc(struct IsdnCardState *cs)
678 {
679 	INIT_WORK(&cs->tqueue, icc_bh);
680 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
681 	cs->dbusytimer.data = (long) cs;
682 	init_timer(&cs->dbusytimer);
683 }
684