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