• 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 #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 	init_timer(&cs->dbusytimer);
172 	cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
173 	add_timer(&cs->dbusytimer);
174 	if (cs->debug & L1_DEB_ISAC_FIFO) {
175 		char *t = cs->dlog;
176 
177 		t += sprintf(t, "icc_fill_fifo cnt %d", count);
178 		QuickHex(t, ptr, count);
179 		debugl1(cs, "%s", cs->dlog);
180 	}
181 }
182 
183 void
icc_interrupt(struct IsdnCardState * cs,u_char val)184 icc_interrupt(struct IsdnCardState *cs, u_char val)
185 {
186 	u_char exval, v1;
187 	struct sk_buff *skb;
188 	unsigned int count;
189 
190 	if (cs->debug & L1_DEB_ISAC)
191 		debugl1(cs, "ICC interrupt %x", val);
192 	if (val & 0x80) {	/* RME */
193 		exval = cs->readisac(cs, ICC_RSTA);
194 		if ((exval & 0x70) != 0x20) {
195 			if (exval & 0x40) {
196 				if (cs->debug & L1_DEB_WARN)
197 					debugl1(cs, "ICC RDO");
198 #ifdef ERROR_STATISTIC
199 				cs->err_rx++;
200 #endif
201 			}
202 			if (!(exval & 0x20)) {
203 				if (cs->debug & L1_DEB_WARN)
204 					debugl1(cs, "ICC CRC error");
205 #ifdef ERROR_STATISTIC
206 				cs->err_crc++;
207 #endif
208 			}
209 			cs->writeisac(cs, ICC_CMDR, 0x80);
210 		} else {
211 			count = cs->readisac(cs, ICC_RBCL) & 0x1f;
212 			if (count == 0)
213 				count = 32;
214 			icc_empty_fifo(cs, count);
215 			if ((count = cs->rcvidx) > 0) {
216 				cs->rcvidx = 0;
217 				if (!(skb = alloc_skb(count, GFP_ATOMIC)))
218 					printk(KERN_WARNING "HiSax: D receive out of memory\n");
219 				else {
220 					memcpy(skb_put(skb, count), cs->rcvbuf, count);
221 					skb_queue_tail(&cs->rq, skb);
222 				}
223 			}
224 		}
225 		cs->rcvidx = 0;
226 		schedule_event(cs, D_RCVBUFREADY);
227 	}
228 	if (val & 0x40) {	/* RPF */
229 		icc_empty_fifo(cs, 32);
230 	}
231 	if (val & 0x20) {	/* RSC */
232 		/* never */
233 		if (cs->debug & L1_DEB_WARN)
234 			debugl1(cs, "ICC RSC interrupt");
235 	}
236 	if (val & 0x10) {	/* XPR */
237 		if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
238 			del_timer(&cs->dbusytimer);
239 		if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
240 			schedule_event(cs, D_CLEARBUSY);
241 		if (cs->tx_skb) {
242 			if (cs->tx_skb->len) {
243 				icc_fill_fifo(cs);
244 				goto afterXPR;
245 			} else {
246 				dev_kfree_skb_irq(cs->tx_skb);
247 				cs->tx_cnt = 0;
248 				cs->tx_skb = NULL;
249 			}
250 		}
251 		if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
252 			cs->tx_cnt = 0;
253 			icc_fill_fifo(cs);
254 		} else
255 			schedule_event(cs, D_XMTBUFREADY);
256 	}
257 afterXPR:
258 	if (val & 0x04) {	/* CISQ */
259 		exval = cs->readisac(cs, ICC_CIR0);
260 		if (cs->debug & L1_DEB_ISAC)
261 			debugl1(cs, "ICC CIR0 %02X", exval);
262 		if (exval & 2) {
263 			cs->dc.icc.ph_state = (exval >> 2) & 0xf;
264 			if (cs->debug & L1_DEB_ISAC)
265 				debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state);
266 			schedule_event(cs, D_L1STATECHANGE);
267 		}
268 		if (exval & 1) {
269 			exval = cs->readisac(cs, ICC_CIR1);
270 			if (cs->debug & L1_DEB_ISAC)
271 				debugl1(cs, "ICC CIR1 %02X", exval);
272 		}
273 	}
274 	if (val & 0x02) {	/* SIN */
275 		/* never */
276 		if (cs->debug & L1_DEB_WARN)
277 			debugl1(cs, "ICC SIN interrupt");
278 	}
279 	if (val & 0x01) {	/* EXI */
280 		exval = cs->readisac(cs, ICC_EXIR);
281 		if (cs->debug & L1_DEB_WARN)
282 			debugl1(cs, "ICC EXIR %02x", exval);
283 		if (exval & 0x80) {  /* XMR */
284 			debugl1(cs, "ICC XMR");
285 			printk(KERN_WARNING "HiSax: ICC XMR\n");
286 		}
287 		if (exval & 0x40) {  /* XDU */
288 			debugl1(cs, "ICC XDU");
289 			printk(KERN_WARNING "HiSax: ICC XDU\n");
290 #ifdef ERROR_STATISTIC
291 			cs->err_tx++;
292 #endif
293 			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
294 				del_timer(&cs->dbusytimer);
295 			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
296 				schedule_event(cs, D_CLEARBUSY);
297 			if (cs->tx_skb) { /* Restart frame */
298 				skb_push(cs->tx_skb, cs->tx_cnt);
299 				cs->tx_cnt = 0;
300 				icc_fill_fifo(cs);
301 			} else {
302 				printk(KERN_WARNING "HiSax: ICC XDU no skb\n");
303 				debugl1(cs, "ICC XDU no skb");
304 			}
305 		}
306 		if (exval & 0x04) {  /* MOS */
307 			v1 = cs->readisac(cs, ICC_MOSR);
308 			if (cs->debug & L1_DEB_MONITOR)
309 				debugl1(cs, "ICC MOSR %02x", v1);
310 #if ARCOFI_USE
311 			if (v1 & 0x08) {
312 				if (!cs->dc.icc.mon_rx) {
313 					if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
314 						if (cs->debug & L1_DEB_WARN)
315 							debugl1(cs, "ICC MON RX out of memory!");
316 						cs->dc.icc.mocr &= 0xf0;
317 						cs->dc.icc.mocr |= 0x0a;
318 						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
319 						goto afterMONR0;
320 					} else
321 						cs->dc.icc.mon_rxp = 0;
322 				}
323 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
324 					cs->dc.icc.mocr &= 0xf0;
325 					cs->dc.icc.mocr |= 0x0a;
326 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
327 					cs->dc.icc.mon_rxp = 0;
328 					if (cs->debug & L1_DEB_WARN)
329 						debugl1(cs, "ICC MON RX overflow!");
330 					goto afterMONR0;
331 				}
332 				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0);
333 				if (cs->debug & L1_DEB_MONITOR)
334 					debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp - 1]);
335 				if (cs->dc.icc.mon_rxp == 1) {
336 					cs->dc.icc.mocr |= 0x04;
337 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
338 				}
339 			}
340 		afterMONR0:
341 			if (v1 & 0x80) {
342 				if (!cs->dc.icc.mon_rx) {
343 					if (!(cs->dc.icc.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) {
344 						if (cs->debug & L1_DEB_WARN)
345 							debugl1(cs, "ICC MON RX out of memory!");
346 						cs->dc.icc.mocr &= 0x0f;
347 						cs->dc.icc.mocr |= 0xa0;
348 						cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
349 						goto afterMONR1;
350 					} else
351 						cs->dc.icc.mon_rxp = 0;
352 				}
353 				if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) {
354 					cs->dc.icc.mocr &= 0x0f;
355 					cs->dc.icc.mocr |= 0xa0;
356 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
357 					cs->dc.icc.mon_rxp = 0;
358 					if (cs->debug & L1_DEB_WARN)
359 						debugl1(cs, "ICC MON RX overflow!");
360 					goto afterMONR1;
361 				}
362 				cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1);
363 				if (cs->debug & L1_DEB_MONITOR)
364 					debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp - 1]);
365 				cs->dc.icc.mocr |= 0x40;
366 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
367 			}
368 		afterMONR1:
369 			if (v1 & 0x04) {
370 				cs->dc.icc.mocr &= 0xf0;
371 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
372 				cs->dc.icc.mocr |= 0x0a;
373 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
374 				schedule_event(cs, D_RX_MON0);
375 			}
376 			if (v1 & 0x40) {
377 				cs->dc.icc.mocr &= 0x0f;
378 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
379 				cs->dc.icc.mocr |= 0xa0;
380 				cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
381 				schedule_event(cs, D_RX_MON1);
382 			}
383 			if (v1 & 0x02) {
384 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
385 							     (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
386 							     !(v1 & 0x08))) {
387 					cs->dc.icc.mocr &= 0xf0;
388 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
389 					cs->dc.icc.mocr |= 0x0a;
390 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
391 					if (cs->dc.icc.mon_txc &&
392 					    (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
393 						schedule_event(cs, D_TX_MON0);
394 					goto AfterMOX0;
395 				}
396 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
397 					schedule_event(cs, D_TX_MON0);
398 					goto AfterMOX0;
399 				}
400 				cs->writeisac(cs, ICC_MOX0,
401 					      cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
402 				if (cs->debug & L1_DEB_MONITOR)
403 					debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]);
404 			}
405 		AfterMOX0:
406 			if (v1 & 0x20) {
407 				if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc &&
408 							     (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) &&
409 							     !(v1 & 0x80))) {
410 					cs->dc.icc.mocr &= 0x0f;
411 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
412 					cs->dc.icc.mocr |= 0xa0;
413 					cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr);
414 					if (cs->dc.icc.mon_txc &&
415 					    (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc))
416 						schedule_event(cs, D_TX_MON1);
417 					goto AfterMOX1;
418 				}
419 				if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) {
420 					schedule_event(cs, D_TX_MON1);
421 					goto AfterMOX1;
422 				}
423 				cs->writeisac(cs, ICC_MOX1,
424 					      cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]);
425 				if (cs->debug & L1_DEB_MONITOR)
426 					debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp - 1]);
427 			}
428 		AfterMOX1: ;
429 #endif
430 		}
431 	}
432 }
433 
434 static void
ICC_l1hw(struct PStack * st,int pr,void * arg)435 ICC_l1hw(struct PStack *st, int pr, void *arg)
436 {
437 	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
438 	struct sk_buff *skb = arg;
439 	u_long flags;
440 	int  val;
441 
442 	switch (pr) {
443 	case (PH_DATA | REQUEST):
444 		if (cs->debug & DEB_DLOG_HEX)
445 			LogFrame(cs, skb->data, skb->len);
446 		if (cs->debug & DEB_DLOG_VERBOSE)
447 			dlogframe(cs, skb, 0);
448 		spin_lock_irqsave(&cs->lock, flags);
449 		if (cs->tx_skb) {
450 			skb_queue_tail(&cs->sq, skb);
451 #ifdef L2FRAME_DEBUG		/* psa */
452 			if (cs->debug & L1_DEB_LAPD)
453 				Logl2Frame(cs, skb, "PH_DATA Queued", 0);
454 #endif
455 		} else {
456 			cs->tx_skb = skb;
457 			cs->tx_cnt = 0;
458 #ifdef L2FRAME_DEBUG		/* psa */
459 			if (cs->debug & L1_DEB_LAPD)
460 				Logl2Frame(cs, skb, "PH_DATA", 0);
461 #endif
462 			icc_fill_fifo(cs);
463 		}
464 		spin_unlock_irqrestore(&cs->lock, flags);
465 		break;
466 	case (PH_PULL | INDICATION):
467 		spin_lock_irqsave(&cs->lock, flags);
468 		if (cs->tx_skb) {
469 			if (cs->debug & L1_DEB_WARN)
470 				debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
471 			skb_queue_tail(&cs->sq, skb);
472 			spin_unlock_irqrestore(&cs->lock, flags);
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 
setup_icc(struct IsdnCardState * cs)676 void setup_icc(struct IsdnCardState *cs)
677 {
678 	INIT_WORK(&cs->tqueue, icc_bh);
679 	cs->dbusytimer.function = (void *) dbusy_timer_handler;
680 	cs->dbusytimer.data = (long) cs;
681 	init_timer(&cs->dbusytimer);
682 }
683