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