~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/isdn/hisax/icc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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