OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [isdn/] [hisax/] [hscx_irq.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $
2
 *
3
 * low level b-channel stuff for Siemens HSCX
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
 * This is an include file for fast inline IRQ stuff
12
 *
13
 */
14
 
15
 
16
static inline void
17
waitforCEC(struct IsdnCardState *cs, int hscx)
18
{
19
        int to = 50;
20
 
21
        while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
22
                udelay(1);
23
                to--;
24
        }
25
        if (!to)
26
                printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
27
}
28
 
29
 
30
static inline void
31
waitforXFW(struct IsdnCardState *cs, int hscx)
32
{
33
        int to = 50;
34
 
35
        while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
36
                udelay(1);
37
                to--;
38
        }
39
        if (!to)
40
                printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
41
}
42
 
43
static inline void
44
WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
45
{
46
        waitforCEC(cs, hscx);
47
        WRITEHSCX(cs, hscx, HSCX_CMDR, data);
48
}
49
 
50
 
51
 
52
static void
53
hscx_empty_fifo(struct BCState *bcs, int count)
54
{
55
        u_char *ptr;
56
        struct IsdnCardState *cs = bcs->cs;
57
 
58
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
59
                debugl1(cs, "hscx_empty_fifo");
60
 
61
        if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
62
                if (cs->debug & L1_DEB_WARN)
63
                        debugl1(cs, "hscx_empty_fifo: incoming packet too large");
64
                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
65
                bcs->hw.hscx.rcvidx = 0;
66
                return;
67
        }
68
        ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
69
        bcs->hw.hscx.rcvidx += count;
70
        READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
71
        WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
72
        if (cs->debug & L1_DEB_HSCX_FIFO) {
73
                char *t = bcs->blog;
74
 
75
                t += sprintf(t, "hscx_empty_fifo %c cnt %d",
76
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
77
                QuickHex(t, ptr, count);
78
                debugl1(cs, bcs->blog);
79
        }
80
}
81
 
82
static void
83
hscx_fill_fifo(struct BCState *bcs)
84
{
85
        struct IsdnCardState *cs = bcs->cs;
86
        int more, count;
87
        int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
88
        u_char *ptr;
89
 
90
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
91
                debugl1(cs, "hscx_fill_fifo");
92
 
93
        if (!bcs->tx_skb)
94
                return;
95
        if (bcs->tx_skb->len <= 0)
96
                return;
97
 
98
        more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
99
        if (bcs->tx_skb->len > fifo_size) {
100
                more = !0;
101
                count = fifo_size;
102
        } else
103
                count = bcs->tx_skb->len;
104
 
105
        waitforXFW(cs, bcs->hw.hscx.hscx);
106
        ptr = bcs->tx_skb->data;
107
        skb_pull(bcs->tx_skb, count);
108
        bcs->tx_cnt -= count;
109
        bcs->hw.hscx.count += count;
110
        WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
111
        WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
112
        if (cs->debug & L1_DEB_HSCX_FIFO) {
113
                char *t = bcs->blog;
114
 
115
                t += sprintf(t, "hscx_fill_fifo %c cnt %d",
116
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
117
                QuickHex(t, ptr, count);
118
                debugl1(cs, bcs->blog);
119
        }
120
}
121
 
122
static void
123
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
124
{
125
        u_char r;
126
        struct BCState *bcs = cs->bcs + hscx;
127
        struct sk_buff *skb;
128
        int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
129
        int count;
130
 
131
        if (!test_bit(BC_FLG_INIT, &bcs->Flag))
132
                return;
133
 
134
        if (val & 0x80) {       /* RME */
135
                r = READHSCX(cs, hscx, HSCX_RSTA);
136
                if ((r & 0xf0) != 0xa0) {
137
                        if (!(r & 0x80)) {
138
                                if (cs->debug & L1_DEB_WARN)
139
                                        debugl1(cs, "HSCX invalid frame");
140
#ifdef ERROR_STATISTIC
141
                                bcs->err_inv++;
142
#endif
143
                        }
144
                        if ((r & 0x40) && bcs->mode) {
145
                                if (cs->debug & L1_DEB_WARN)
146
                                        debugl1(cs, "HSCX RDO mode=%d",
147
                                                bcs->mode);
148
#ifdef ERROR_STATISTIC
149
                                bcs->err_rdo++;
150
#endif
151
                        }
152
                        if (!(r & 0x20)) {
153
                                if (cs->debug & L1_DEB_WARN)
154
                                        debugl1(cs, "HSCX CRC error");
155
#ifdef ERROR_STATISTIC
156
                                bcs->err_crc++;
157
#endif
158
                        }
159
                        WriteHSCXCMDR(cs, hscx, 0x80);
160
                } else {
161
                        count = READHSCX(cs, hscx, HSCX_RBCL) & (
162
                                test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
163
                        if (count == 0)
164
                                count = fifo_size;
165
                        hscx_empty_fifo(bcs, count);
166
                        if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
167
                                if (cs->debug & L1_DEB_HSCX_FIFO)
168
                                        debugl1(cs, "HX Frame %d", count);
169
                                if (!(skb = dev_alloc_skb(count)))
170
                                        printk(KERN_WARNING "HSCX: receive out of memory\n");
171
                                else {
172
                                        memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
173
                                        skb_queue_tail(&bcs->rqueue, skb);
174
                                }
175
                        }
176
                }
177
                bcs->hw.hscx.rcvidx = 0;
178
                schedule_event(bcs, B_RCVBUFREADY);
179
        }
180
        if (val & 0x40) {       /* RPF */
181
                hscx_empty_fifo(bcs, fifo_size);
182
                if (bcs->mode == L1_MODE_TRANS) {
183
                        /* receive audio data */
184
                        if (!(skb = dev_alloc_skb(fifo_size)))
185
                                printk(KERN_WARNING "HiSax: receive out of memory\n");
186
                        else {
187
                                memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
188
                                skb_queue_tail(&bcs->rqueue, skb);
189
                        }
190
                        bcs->hw.hscx.rcvidx = 0;
191
                        schedule_event(bcs, B_RCVBUFREADY);
192
                }
193
        }
194
        if (val & 0x10) {       /* XPR */
195
                if (bcs->tx_skb) {
196
                        if (bcs->tx_skb->len) {
197
                                hscx_fill_fifo(bcs);
198
                                return;
199
                        } else {
200
                                if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
201
                                        (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
202
                                        u_long  flags;
203
                                        spin_lock_irqsave(&bcs->aclock, flags);
204
                                        bcs->ackcnt += bcs->hw.hscx.count;
205
                                        spin_unlock_irqrestore(&bcs->aclock, flags);
206
                                        schedule_event(bcs, B_ACKPENDING);
207
                                }
208
                                dev_kfree_skb_irq(bcs->tx_skb);
209
                                bcs->hw.hscx.count = 0;
210
                                bcs->tx_skb = NULL;
211
                        }
212
                }
213
                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
214
                        bcs->hw.hscx.count = 0;
215
                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
216
                        hscx_fill_fifo(bcs);
217
                } else {
218
                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
219
                        schedule_event(bcs, B_XMTBUFREADY);
220
                }
221
        }
222
}
223
 
224
static void
225
hscx_int_main(struct IsdnCardState *cs, u_char val)
226
{
227
 
228
        u_char exval;
229
        struct BCState *bcs;
230
 
231
        if (val & 0x01) {
232
                bcs = cs->bcs + 1;
233
                exval = READHSCX(cs, 1, HSCX_EXIR);
234
                if (exval & 0x40) {
235
                        if (bcs->mode == 1)
236
                                hscx_fill_fifo(bcs);
237
                        else {
238
#ifdef ERROR_STATISTIC
239
                                bcs->err_tx++;
240
#endif
241
                                /* Here we lost an TX interrupt, so
242
                                   * restart transmitting the whole frame.
243
                                 */
244
                                if (bcs->tx_skb) {
245
                                        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
246
                                        bcs->tx_cnt += bcs->hw.hscx.count;
247
                                        bcs->hw.hscx.count = 0;
248
                                }
249
                                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
250
                                if (cs->debug & L1_DEB_WARN)
251
                                        debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
252
                        }
253
                } else if (cs->debug & L1_DEB_HSCX)
254
                        debugl1(cs, "HSCX B EXIR %x", exval);
255
        }
256
        if (val & 0xf8) {
257
                if (cs->debug & L1_DEB_HSCX)
258
                        debugl1(cs, "HSCX B interrupt %x", val);
259
                hscx_interrupt(cs, val, 1);
260
        }
261
        if (val & 0x02) {
262
                bcs = cs->bcs;
263
                exval = READHSCX(cs, 0, HSCX_EXIR);
264
                if (exval & 0x40) {
265
                        if (bcs->mode == L1_MODE_TRANS)
266
                                hscx_fill_fifo(bcs);
267
                        else {
268
                                /* Here we lost an TX interrupt, so
269
                                   * restart transmitting the whole frame.
270
                                 */
271
#ifdef ERROR_STATISTIC
272
                                bcs->err_tx++;
273
#endif
274
                                if (bcs->tx_skb) {
275
                                        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
276
                                        bcs->tx_cnt += bcs->hw.hscx.count;
277
                                        bcs->hw.hscx.count = 0;
278
                                }
279
                                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
280
                                if (cs->debug & L1_DEB_WARN)
281
                                        debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
282
                        }
283
                } else if (cs->debug & L1_DEB_HSCX)
284
                        debugl1(cs, "HSCX A EXIR %x", exval);
285
        }
286
        if (val & 0x04) {
287
                exval = READHSCX(cs, 0, HSCX_ISTA);
288
                if (cs->debug & L1_DEB_HSCX)
289
                        debugl1(cs, "HSCX A interrupt %x", exval);
290
                hscx_interrupt(cs, exval, 0);
291
        }
292
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.