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, 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, 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 
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