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