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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [isdn/] [hisax/] [hscx_irq.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/* $Id: hscx_irq.c,v 1.1 2005-12-20 10:17:01 jcastillo Exp $
2
 
3
 * hscx_irq.c     low level b-channel stuff for Siemens HSCX
4
 *
5
 * Author     Karsten Keil (keil@isdn4linux.de)
6
 *
7
 * This is an include file for fast inline IRQ stuff
8
 *
9
 * $Log: not supported by cvs2svn $
10
 * Revision 1.1.1.1  2001/09/10 07:44:18  simons
11
 * Initial import
12
 *
13
 * Revision 1.1.1.1  2001/07/02 17:58:32  simons
14
 * Initial revision
15
 *
16
 * Revision 1.5.2.5  1998/11/03 00:06:39  keil
17
 * certification related changes
18
 * fixed logging for smaller stack use
19
 *
20
 * Revision 1.5.2.4  1998/09/27 13:06:16  keil
21
 * Apply most changes from 2.1.X (HiSax 3.1)
22
 *
23
 * Revision 1.5.2.3  1998/06/24 14:43:56  keil
24
 * Fix recovery of TX IRQ loss
25
 *
26
 * Revision 1.5.2.2  1998/05/27 18:05:36  keil
27
 * HiSax 3.0
28
 *
29
 * Revision 1.5.2.1  1997/10/17 22:10:46  keil
30
 * new files on 2.0
31
 *
32
 * Revision 1.4  1997/08/15 17:48:02  keil
33
 * cosmetic
34
 *
35
 * Revision 1.3  1997/07/27 21:38:36  keil
36
 * new B-channel interface
37
 *
38
 * Revision 1.2  1997/06/26 11:16:19  keil
39
 * first version
40
 *
41
 *
42
 */
43
 
44
 
45
static inline void
46
waitforCEC(struct IsdnCardState *cs, int hscx)
47
{
48
        int to = 50;
49
 
50
        while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) {
51
                udelay(1);
52
                to--;
53
        }
54
        if (!to)
55
                printk(KERN_WARNING "HiSax: waitforCEC timeout\n");
56
}
57
 
58
 
59
static inline void
60
waitforXFW(struct IsdnCardState *cs, int hscx)
61
{
62
        int to = 50;
63
 
64
        while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) {
65
                udelay(1);
66
                to--;
67
        }
68
        if (!to)
69
                printk(KERN_WARNING "HiSax: waitforXFW timeout\n");
70
}
71
 
72
static inline void
73
WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data)
74
{
75
        long flags;
76
 
77
        save_flags(flags);
78
        cli();
79
        waitforCEC(cs, hscx);
80
        WRITEHSCX(cs, hscx, HSCX_CMDR, data);
81
        restore_flags(flags);
82
}
83
 
84
 
85
 
86
static void
87
hscx_empty_fifo(struct BCState *bcs, int count)
88
{
89
        u_char *ptr;
90
        struct IsdnCardState *cs = bcs->cs;
91
        long flags;
92
 
93
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
94
                debugl1(cs, "hscx_empty_fifo");
95
 
96
        if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) {
97
                if (cs->debug & L1_DEB_WARN)
98
                        debugl1(cs, "hscx_empty_fifo: incoming packet too large");
99
                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
100
                bcs->hw.hscx.rcvidx = 0;
101
                return;
102
        }
103
        ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx;
104
        bcs->hw.hscx.rcvidx += count;
105
        save_flags(flags);
106
        cli();
107
        READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
108
        WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80);
109
        restore_flags(flags);
110
        if (cs->debug & L1_DEB_HSCX_FIFO) {
111
                char *t = bcs->blog;
112
 
113
                t += sprintf(t, "hscx_empty_fifo %c cnt %d",
114
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
115
                QuickHex(t, ptr, count);
116
                debugl1(cs, bcs->blog);
117
        }
118
}
119
 
120
static void
121
hscx_fill_fifo(struct BCState *bcs)
122
{
123
        struct IsdnCardState *cs = bcs->cs;
124
        int more, count;
125
        int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
126
        u_char *ptr;
127
        long flags;
128
 
129
 
130
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
131
                debugl1(cs, "hscx_fill_fifo");
132
 
133
        if (!bcs->tx_skb)
134
                return;
135
        if (bcs->tx_skb->len <= 0)
136
                return;
137
 
138
        more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0;
139
        if (bcs->tx_skb->len > fifo_size) {
140
                more = !0;
141
                count = fifo_size;
142
        } else
143
                count = bcs->tx_skb->len;
144
 
145
        waitforXFW(cs, bcs->hw.hscx.hscx);
146
        save_flags(flags);
147
        cli();
148
        ptr = bcs->tx_skb->data;
149
        skb_pull(bcs->tx_skb, count);
150
        bcs->tx_cnt -= count;
151
        bcs->hw.hscx.count += count;
152
        WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count);
153
        WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa);
154
        restore_flags(flags);
155
        if (cs->debug & L1_DEB_HSCX_FIFO) {
156
                char *t = bcs->blog;
157
 
158
                t += sprintf(t, "hscx_fill_fifo %c cnt %d",
159
                             bcs->hw.hscx.hscx ? 'B' : 'A', count);
160
                QuickHex(t, ptr, count);
161
                debugl1(cs, bcs->blog);
162
        }
163
}
164
 
165
static inline void
166
hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx)
167
{
168
        u_char r;
169
        struct BCState *bcs = cs->bcs + hscx;
170
        struct sk_buff *skb;
171
        int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32;
172
        int count;
173
 
174
        if (!test_bit(BC_FLG_INIT, &bcs->Flag))
175
                return;
176
 
177
        if (val & 0x80) {       /* RME */
178
                r = READHSCX(cs, hscx, HSCX_RSTA);
179
                if ((r & 0xf0) != 0xa0) {
180
                        if (!(r & 0x80))
181
                                if (cs->debug & L1_DEB_WARN)
182
                                        debugl1(cs, "HSCX invalid frame");
183
                        if ((r & 0x40) && bcs->mode)
184
                                if (cs->debug & L1_DEB_WARN)
185
                                        debugl1(cs, "HSCX RDO mode=%d",
186
                                                bcs->mode);
187
                        if (!(r & 0x20))
188
                                if (cs->debug & L1_DEB_WARN)
189
                                        debugl1(cs, "HSCX CRC error");
190
                        WriteHSCXCMDR(cs, hscx, 0x80);
191
                } else {
192
                        count = READHSCX(cs, hscx, HSCX_RBCL) & (
193
                                test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f);
194
                        if (count == 0)
195
                                count = fifo_size;
196
                        hscx_empty_fifo(bcs, count);
197
                        if ((count = bcs->hw.hscx.rcvidx - 1) > 0) {
198
                                if (cs->debug & L1_DEB_HSCX_FIFO)
199
                                        debugl1(cs, "HX Frame %d", count);
200
                                if (!(skb = dev_alloc_skb(count)))
201
                                        printk(KERN_WARNING "HSCX: receive out of memory\n");
202
                                else {
203
                                        SET_SKB_FREE(skb);
204
                                        memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count);
205
                                        skb_queue_tail(&bcs->rqueue, skb);
206
                                }
207
                        }
208
                }
209
                bcs->hw.hscx.rcvidx = 0;
210
                hscx_sched_event(bcs, B_RCVBUFREADY);
211
        }
212
        if (val & 0x40) {       /* RPF */
213
                hscx_empty_fifo(bcs, fifo_size);
214
                if (bcs->mode == L1_MODE_TRANS) {
215
                        /* receive audio data */
216
                        if (!(skb = dev_alloc_skb(fifo_size)))
217
                                printk(KERN_WARNING "HiSax: receive out of memory\n");
218
                        else {
219
                                SET_SKB_FREE(skb);
220
                                memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size);
221
                                skb_queue_tail(&bcs->rqueue, skb);
222
                        }
223
                        bcs->hw.hscx.rcvidx = 0;
224
                        hscx_sched_event(bcs, B_RCVBUFREADY);
225
                }
226
        }
227
        if (val & 0x10) {       /* XPR */
228
                if (bcs->tx_skb) {
229
                        if (bcs->tx_skb->len) {
230
                                hscx_fill_fifo(bcs);
231
                                return;
232
                        } else {
233
                                if (bcs->st->lli.l1writewakeup &&
234
                                        (PACKET_NOACK != bcs->tx_skb->pkt_type))
235
                                        bcs->st->lli.l1writewakeup(bcs->st, bcs->hw.hscx.count);
236
                                dev_kfree_skb(bcs->tx_skb, FREE_WRITE);
237
                                bcs->hw.hscx.count = 0;
238
                                bcs->tx_skb = NULL;
239
                        }
240
                }
241
                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
242
                        bcs->hw.hscx.count = 0;
243
                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
244
                        hscx_fill_fifo(bcs);
245
                } else {
246
                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
247
                        hscx_sched_event(bcs, B_XMTBUFREADY);
248
                }
249
        }
250
}
251
 
252
static inline void
253
hscx_int_main(struct IsdnCardState *cs, u_char val)
254
{
255
 
256
        u_char exval;
257
        struct BCState *bcs;
258
 
259
        if (val & 0x01) {
260
                bcs = cs->bcs + 1;
261
                exval = READHSCX(cs, 1, HSCX_EXIR);
262
                if (exval & 0x40) {
263
                        if (bcs->mode == 1)
264
                                hscx_fill_fifo(bcs);
265
                        else {
266
                                /* Here we lost an TX interrupt, so
267
                                   * restart transmitting the whole frame.
268
                                 */
269
                                if (bcs->tx_skb) {
270
                                        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
271
                                        bcs->tx_cnt += bcs->hw.hscx.count;
272
                                        bcs->hw.hscx.count = 0;
273
                                }
274
                                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
275
                                if (cs->debug & L1_DEB_WARN)
276
                                        debugl1(cs, "HSCX B EXIR %x Lost TX", exval);
277
                        }
278
                } else if (cs->debug & L1_DEB_HSCX)
279
                        debugl1(cs, "HSCX B EXIR %x", exval);
280
        }
281
        if (val & 0xf8) {
282
                if (cs->debug & L1_DEB_HSCX)
283
                        debugl1(cs, "HSCX B interrupt %x", val);
284
                hscx_interrupt(cs, val, 1);
285
        }
286
        if (val & 0x02) {
287
                bcs = cs->bcs;
288
                exval = READHSCX(cs, 0, HSCX_EXIR);
289
                if (exval & 0x40) {
290
                        if (bcs->mode == L1_MODE_TRANS)
291
                                hscx_fill_fifo(bcs);
292
                        else {
293
                                /* Here we lost an TX interrupt, so
294
                                   * restart transmitting the whole frame.
295
                                 */
296
                                if (bcs->tx_skb) {
297
                                        skb_push(bcs->tx_skb, bcs->hw.hscx.count);
298
                                        bcs->tx_cnt += bcs->hw.hscx.count;
299
                                        bcs->hw.hscx.count = 0;
300
                                }
301
                                WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01);
302
                                if (cs->debug & L1_DEB_WARN)
303
                                        debugl1(cs, "HSCX A EXIR %x Lost TX", exval);
304
                        }
305
                } else if (cs->debug & L1_DEB_HSCX)
306
                        debugl1(cs, "HSCX A EXIR %x", exval);
307
        }
308
        if (val & 0x04) {
309
                exval = READHSCX(cs, 0, HSCX_ISTA);
310
                if (cs->debug & L1_DEB_HSCX)
311
                        debugl1(cs, "HSCX A interrupt %x", exval);
312
                hscx_interrupt(cs, exval, 0);
313
        }
314
}

powered by: WebSVN 2.1.0

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