Merge remote-tracking branch 'asoc/topic/max98371' into asoc-next
[cascardo/linux.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         init_timer(&cs->dbusytimer);
175         cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000);
176         add_timer(&cs->dbusytimer);
177         if (cs->debug & L1_DEB_ISAC_FIFO) {
178                 char *t = cs->dlog;
179
180                 t += sprintf(t, "isac_fill_fifo cnt %d", count);
181                 QuickHex(t, ptr, count);
182                 debugl1(cs, "%s", cs->dlog);
183         }
184 }
185
186 void
187 isac_interrupt(struct IsdnCardState *cs, u_char val)
188 {
189         u_char exval, v1;
190         struct sk_buff *skb;
191         unsigned int count;
192
193         if (cs->debug & L1_DEB_ISAC)
194                 debugl1(cs, "ISAC interrupt %x", val);
195         if (val & 0x80) {       /* RME */
196                 exval = cs->readisac(cs, ISAC_RSTA);
197                 if ((exval & 0x70) != 0x20) {
198                         if (exval & 0x40) {
199                                 if (cs->debug & L1_DEB_WARN)
200                                         debugl1(cs, "ISAC RDO");
201 #ifdef ERROR_STATISTIC
202                                 cs->err_rx++;
203 #endif
204                         }
205                         if (!(exval & 0x20)) {
206                                 if (cs->debug & L1_DEB_WARN)
207                                         debugl1(cs, "ISAC CRC error");
208 #ifdef ERROR_STATISTIC
209                                 cs->err_crc++;
210 #endif
211                         }
212                         cs->writeisac(cs, ISAC_CMDR, 0x80);
213                 } else {
214                         count = cs->readisac(cs, ISAC_RBCL) & 0x1f;
215                         if (count == 0)
216                                 count = 32;
217                         isac_empty_fifo(cs, count);
218                         count = cs->rcvidx;
219                         if (count > 0) {
220                                 cs->rcvidx = 0;
221                                 skb = alloc_skb(count, GFP_ATOMIC);
222                                 if (!skb)
223                                         printk(KERN_WARNING "HiSax: D receive out of memory\n");
224                                 else {
225                                         memcpy(skb_put(skb, count), cs->rcvbuf, count);
226                                         skb_queue_tail(&cs->rq, skb);
227                                 }
228                         }
229                 }
230                 cs->rcvidx = 0;
231                 schedule_event(cs, D_RCVBUFREADY);
232         }
233         if (val & 0x40) {       /* RPF */
234                 isac_empty_fifo(cs, 32);
235         }
236         if (val & 0x20) {       /* RSC */
237                 /* never */
238                 if (cs->debug & L1_DEB_WARN)
239                         debugl1(cs, "ISAC RSC interrupt");
240         }
241         if (val & 0x10) {       /* XPR */
242                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
243                         del_timer(&cs->dbusytimer);
244                 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
245                         schedule_event(cs, D_CLEARBUSY);
246                 if (cs->tx_skb) {
247                         if (cs->tx_skb->len) {
248                                 isac_fill_fifo(cs);
249                                 goto afterXPR;
250                         } else {
251                                 dev_kfree_skb_irq(cs->tx_skb);
252                                 cs->tx_cnt = 0;
253                                 cs->tx_skb = NULL;
254                         }
255                 }
256                 cs->tx_skb = skb_dequeue(&cs->sq);
257                 if (cs->tx_skb) {
258                         cs->tx_cnt = 0;
259                         isac_fill_fifo(cs);
260                 } else
261                         schedule_event(cs, D_XMTBUFREADY);
262         }
263 afterXPR:
264         if (val & 0x04) {       /* CISQ */
265                 exval = cs->readisac(cs, ISAC_CIR0);
266                 if (cs->debug & L1_DEB_ISAC)
267                         debugl1(cs, "ISAC CIR0 %02X", exval);
268                 if (exval & 2) {
269                         cs->dc.isac.ph_state = (exval >> 2) & 0xf;
270                         if (cs->debug & L1_DEB_ISAC)
271                                 debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state);
272                         schedule_event(cs, D_L1STATECHANGE);
273                 }
274                 if (exval & 1) {
275                         exval = cs->readisac(cs, ISAC_CIR1);
276                         if (cs->debug & L1_DEB_ISAC)
277                                 debugl1(cs, "ISAC CIR1 %02X", exval);
278                 }
279         }
280         if (val & 0x02) {       /* SIN */
281                 /* never */
282                 if (cs->debug & L1_DEB_WARN)
283                         debugl1(cs, "ISAC SIN interrupt");
284         }
285         if (val & 0x01) {       /* EXI */
286                 exval = cs->readisac(cs, ISAC_EXIR);
287                 if (cs->debug & L1_DEB_WARN)
288                         debugl1(cs, "ISAC EXIR %02x", exval);
289                 if (exval & 0x80) {  /* XMR */
290                         debugl1(cs, "ISAC XMR");
291                         printk(KERN_WARNING "HiSax: ISAC XMR\n");
292                 }
293                 if (exval & 0x40) {  /* XDU */
294                         debugl1(cs, "ISAC XDU");
295                         printk(KERN_WARNING "HiSax: ISAC XDU\n");
296 #ifdef ERROR_STATISTIC
297                         cs->err_tx++;
298 #endif
299                         if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
300                                 del_timer(&cs->dbusytimer);
301                         if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
302                                 schedule_event(cs, D_CLEARBUSY);
303                         if (cs->tx_skb) { /* Restart frame */
304                                 skb_push(cs->tx_skb, cs->tx_cnt);
305                                 cs->tx_cnt = 0;
306                                 isac_fill_fifo(cs);
307                         } else {
308                                 printk(KERN_WARNING "HiSax: ISAC XDU no skb\n");
309                                 debugl1(cs, "ISAC XDU no skb");
310                         }
311                 }
312                 if (exval & 0x04) {  /* MOS */
313                         v1 = cs->readisac(cs, ISAC_MOSR);
314                         if (cs->debug & L1_DEB_MONITOR)
315                                 debugl1(cs, "ISAC MOSR %02x", v1);
316 #if ARCOFI_USE
317                         if (v1 & 0x08) {
318                                 if (!cs->dc.isac.mon_rx) {
319                                         cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
320                                         if (!cs->dc.isac.mon_rx) {
321                                                 if (cs->debug & L1_DEB_WARN)
322                                                         debugl1(cs, "ISAC MON RX out of memory!");
323                                                 cs->dc.isac.mocr &= 0xf0;
324                                                 cs->dc.isac.mocr |= 0x0a;
325                                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
326                                                 goto afterMONR0;
327                                         } else
328                                                 cs->dc.isac.mon_rxp = 0;
329                                 }
330                                 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
331                                         cs->dc.isac.mocr &= 0xf0;
332                                         cs->dc.isac.mocr |= 0x0a;
333                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
334                                         cs->dc.isac.mon_rxp = 0;
335                                         if (cs->debug & L1_DEB_WARN)
336                                                 debugl1(cs, "ISAC MON RX overflow!");
337                                         goto afterMONR0;
338                                 }
339                                 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0);
340                                 if (cs->debug & L1_DEB_MONITOR)
341                                         debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp - 1]);
342                                 if (cs->dc.isac.mon_rxp == 1) {
343                                         cs->dc.isac.mocr |= 0x04;
344                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
345                                 }
346                         }
347                 afterMONR0:
348                         if (v1 & 0x80) {
349                                 if (!cs->dc.isac.mon_rx) {
350                                         cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC);
351                                         if (!cs->dc.isac.mon_rx) {
352                                                 if (cs->debug & L1_DEB_WARN)
353                                                         debugl1(cs, "ISAC MON RX out of memory!");
354                                                 cs->dc.isac.mocr &= 0x0f;
355                                                 cs->dc.isac.mocr |= 0xa0;
356                                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
357                                                 goto afterMONR1;
358                                         } else
359                                                 cs->dc.isac.mon_rxp = 0;
360                                 }
361                                 if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) {
362                                         cs->dc.isac.mocr &= 0x0f;
363                                         cs->dc.isac.mocr |= 0xa0;
364                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
365                                         cs->dc.isac.mon_rxp = 0;
366                                         if (cs->debug & L1_DEB_WARN)
367                                                 debugl1(cs, "ISAC MON RX overflow!");
368                                         goto afterMONR1;
369                                 }
370                                 cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1);
371                                 if (cs->debug & L1_DEB_MONITOR)
372                                         debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp - 1]);
373                                 cs->dc.isac.mocr |= 0x40;
374                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
375                         }
376                 afterMONR1:
377                         if (v1 & 0x04) {
378                                 cs->dc.isac.mocr &= 0xf0;
379                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
380                                 cs->dc.isac.mocr |= 0x0a;
381                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
382                                 schedule_event(cs, D_RX_MON0);
383                         }
384                         if (v1 & 0x40) {
385                                 cs->dc.isac.mocr &= 0x0f;
386                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
387                                 cs->dc.isac.mocr |= 0xa0;
388                                 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
389                                 schedule_event(cs, D_RX_MON1);
390                         }
391                         if (v1 & 0x02) {
392                                 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
393                                                               (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
394                                                               !(v1 & 0x08))) {
395                                         cs->dc.isac.mocr &= 0xf0;
396                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
397                                         cs->dc.isac.mocr |= 0x0a;
398                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
399                                         if (cs->dc.isac.mon_txc &&
400                                             (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
401                                                 schedule_event(cs, D_TX_MON0);
402                                         goto AfterMOX0;
403                                 }
404                                 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
405                                         schedule_event(cs, D_TX_MON0);
406                                         goto AfterMOX0;
407                                 }
408                                 cs->writeisac(cs, ISAC_MOX0,
409                                               cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
410                                 if (cs->debug & L1_DEB_MONITOR)
411                                         debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp - 1]);
412                         }
413                 AfterMOX0:
414                         if (v1 & 0x20) {
415                                 if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc &&
416                                                               (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) &&
417                                                               !(v1 & 0x80))) {
418                                         cs->dc.isac.mocr &= 0x0f;
419                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
420                                         cs->dc.isac.mocr |= 0xa0;
421                                         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
422                                         if (cs->dc.isac.mon_txc &&
423                                             (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc))
424                                                 schedule_event(cs, D_TX_MON1);
425                                         goto AfterMOX1;
426                                 }
427                                 if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) {
428                                         schedule_event(cs, D_TX_MON1);
429                                         goto AfterMOX1;
430                                 }
431                                 cs->writeisac(cs, ISAC_MOX1,
432                                               cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
433                                 if (cs->debug & L1_DEB_MONITOR)
434                                         debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp - 1]);
435                         }
436                 AfterMOX1:;
437 #endif
438                 }
439         }
440 }
441
442 static void
443 ISAC_l1hw(struct PStack *st, int pr, void *arg)
444 {
445         struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
446         struct sk_buff *skb = arg;
447         u_long flags;
448         int  val;
449
450         switch (pr) {
451         case (PH_DATA | REQUEST):
452                 if (cs->debug & DEB_DLOG_HEX)
453                         LogFrame(cs, skb->data, skb->len);
454                 if (cs->debug & DEB_DLOG_VERBOSE)
455                         dlogframe(cs, skb, 0);
456                 spin_lock_irqsave(&cs->lock, flags);
457                 if (cs->tx_skb) {
458                         skb_queue_tail(&cs->sq, skb);
459 #ifdef L2FRAME_DEBUG            /* psa */
460                         if (cs->debug & L1_DEB_LAPD)
461                                 Logl2Frame(cs, skb, "PH_DATA Queued", 0);
462 #endif
463                 } else {
464                         cs->tx_skb = skb;
465                         cs->tx_cnt = 0;
466 #ifdef L2FRAME_DEBUG            /* psa */
467                         if (cs->debug & L1_DEB_LAPD)
468                                 Logl2Frame(cs, skb, "PH_DATA", 0);
469 #endif
470                         isac_fill_fifo(cs);
471                 }
472                 spin_unlock_irqrestore(&cs->lock, flags);
473                 break;
474         case (PH_PULL | INDICATION):
475                 spin_lock_irqsave(&cs->lock, flags);
476                 if (cs->tx_skb) {
477                         if (cs->debug & L1_DEB_WARN)
478                                 debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
479                         skb_queue_tail(&cs->sq, skb);
480                 } else {
481                         if (cs->debug & DEB_DLOG_HEX)
482                                 LogFrame(cs, skb->data, skb->len);
483                         if (cs->debug & DEB_DLOG_VERBOSE)
484                                 dlogframe(cs, skb, 0);
485                         cs->tx_skb = skb;
486                         cs->tx_cnt = 0;
487 #ifdef L2FRAME_DEBUG            /* psa */
488                         if (cs->debug & L1_DEB_LAPD)
489                                 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
490 #endif
491                         isac_fill_fifo(cs);
492                 }
493                 spin_unlock_irqrestore(&cs->lock, flags);
494                 break;
495         case (PH_PULL | REQUEST):
496 #ifdef L2FRAME_DEBUG            /* psa */
497                 if (cs->debug & L1_DEB_LAPD)
498                         debugl1(cs, "-> PH_REQUEST_PULL");
499 #endif
500                 if (!cs->tx_skb) {
501                         test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
502                         st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
503                 } else
504                         test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
505                 break;
506         case (HW_RESET | REQUEST):
507                 spin_lock_irqsave(&cs->lock, flags);
508                 if ((cs->dc.isac.ph_state == ISAC_IND_EI) ||
509                     (cs->dc.isac.ph_state == ISAC_IND_DR) ||
510                     (cs->dc.isac.ph_state == ISAC_IND_RS))
511                         ph_command(cs, ISAC_CMD_TIM);
512                 else
513                         ph_command(cs, ISAC_CMD_RS);
514                 spin_unlock_irqrestore(&cs->lock, flags);
515                 break;
516         case (HW_ENABLE | REQUEST):
517                 spin_lock_irqsave(&cs->lock, flags);
518                 ph_command(cs, ISAC_CMD_TIM);
519                 spin_unlock_irqrestore(&cs->lock, flags);
520                 break;
521         case (HW_INFO3 | REQUEST):
522                 spin_lock_irqsave(&cs->lock, flags);
523                 ph_command(cs, ISAC_CMD_AR8);
524                 spin_unlock_irqrestore(&cs->lock, flags);
525                 break;
526         case (HW_TESTLOOP | REQUEST):
527                 spin_lock_irqsave(&cs->lock, flags);
528                 val = 0;
529                 if (1 & (long) arg)
530                         val |= 0x0c;
531                 if (2 & (long) arg)
532                         val |= 0x3;
533                 if (test_bit(HW_IOM1, &cs->HW_Flags)) {
534                         /* IOM 1 Mode */
535                         if (!val) {
536                                 cs->writeisac(cs, ISAC_SPCR, 0xa);
537                                 cs->writeisac(cs, ISAC_ADF1, 0x2);
538                         } else {
539                                 cs->writeisac(cs, ISAC_SPCR, val);
540                                 cs->writeisac(cs, ISAC_ADF1, 0xa);
541                         }
542                 } else {
543                         /* IOM 2 Mode */
544                         cs->writeisac(cs, ISAC_SPCR, val);
545                         if (val)
546                                 cs->writeisac(cs, ISAC_ADF1, 0x8);
547                         else
548                                 cs->writeisac(cs, ISAC_ADF1, 0x0);
549                 }
550                 spin_unlock_irqrestore(&cs->lock, flags);
551                 break;
552         case (HW_DEACTIVATE | RESPONSE):
553                 skb_queue_purge(&cs->rq);
554                 skb_queue_purge(&cs->sq);
555                 if (cs->tx_skb) {
556                         dev_kfree_skb_any(cs->tx_skb);
557                         cs->tx_skb = NULL;
558                 }
559                 if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
560                         del_timer(&cs->dbusytimer);
561                 if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
562                         schedule_event(cs, D_CLEARBUSY);
563                 break;
564         default:
565                 if (cs->debug & L1_DEB_WARN)
566                         debugl1(cs, "isac_l1hw unknown %04x", pr);
567                 break;
568         }
569 }
570
571 static void
572 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
573 {
574         st->l1.l1hw = ISAC_l1hw;
575 }
576
577 static void
578 DC_Close_isac(struct IsdnCardState *cs)
579 {
580         kfree(cs->dc.isac.mon_rx);
581         cs->dc.isac.mon_rx = NULL;
582         kfree(cs->dc.isac.mon_tx);
583         cs->dc.isac.mon_tx = NULL;
584 }
585
586 static void
587 dbusy_timer_handler(struct IsdnCardState *cs)
588 {
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         cs->dbusytimer.function = (void *) dbusy_timer_handler;
681         cs->dbusytimer.data = (long) cs;
682         init_timer(&cs->dbusytimer);
683 }