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

Subversion Repositories test_project

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $
2
 *
3
 * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
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
 * Thanks to AVM, Berlin for information
12
 *
13
 */
14
 
15
#include <linux/init.h>
16
#include "hisax.h"
17
#include "isac.h"
18
#include "isdnl1.h"
19
#include <linux/pci.h>
20
#include <linux/isapnp.h>
21
#include <linux/interrupt.h>
22
 
23
static const char *avm_pci_rev = "$Revision: 1.29.2.4 $";
24
 
25
#define  AVM_FRITZ_PCI          1
26
#define  AVM_FRITZ_PNP          2
27
 
28
#define  HDLC_FIFO              0x0
29
#define  HDLC_STATUS            0x4
30
 
31
#define  AVM_HDLC_1             0x00
32
#define  AVM_HDLC_2             0x01
33
#define  AVM_ISAC_FIFO          0x02
34
#define  AVM_ISAC_REG_LOW       0x04
35
#define  AVM_ISAC_REG_HIGH      0x06
36
 
37
#define  AVM_STATUS0_IRQ_ISAC   0x01
38
#define  AVM_STATUS0_IRQ_HDLC   0x02
39
#define  AVM_STATUS0_IRQ_TIMER  0x04
40
#define  AVM_STATUS0_IRQ_MASK   0x07
41
 
42
#define  AVM_STATUS0_RESET      0x01
43
#define  AVM_STATUS0_DIS_TIMER  0x02
44
#define  AVM_STATUS0_RES_TIMER  0x04
45
#define  AVM_STATUS0_ENA_IRQ    0x08
46
#define  AVM_STATUS0_TESTBIT    0x10
47
 
48
#define  AVM_STATUS1_INT_SEL    0x0f
49
#define  AVM_STATUS1_ENA_IOM    0x80
50
 
51
#define  HDLC_MODE_ITF_FLG      0x01
52
#define  HDLC_MODE_TRANS        0x02
53
#define  HDLC_MODE_CCR_7        0x04
54
#define  HDLC_MODE_CCR_16       0x08
55
#define  HDLC_MODE_TESTLOOP     0x80
56
 
57
#define  HDLC_INT_XPR           0x80
58
#define  HDLC_INT_XDU           0x40
59
#define  HDLC_INT_RPR           0x20
60
#define  HDLC_INT_MASK          0xE0
61
 
62
#define  HDLC_STAT_RME          0x01
63
#define  HDLC_STAT_RDO          0x10
64
#define  HDLC_STAT_CRCVFRRAB    0x0E
65
#define  HDLC_STAT_CRCVFR       0x06
66
#define  HDLC_STAT_RML_MASK     0x3f00
67
 
68
#define  HDLC_CMD_XRS           0x80
69
#define  HDLC_CMD_XME           0x01
70
#define  HDLC_CMD_RRS           0x20
71
#define  HDLC_CMD_XML_MASK      0x3f00
72
 
73
 
74
/* Interface functions */
75
 
76
static u_char
77
ReadISAC(struct IsdnCardState *cs, u_char offset)
78
{
79
        register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
80
        register u_char val;
81
 
82
        outb(idx, cs->hw.avm.cfg_reg + 4);
83
        val = inb(cs->hw.avm.isac + (offset & 0xf));
84
        return (val);
85
}
86
 
87
static void
88
WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value)
89
{
90
        register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW;
91
 
92
        outb(idx, cs->hw.avm.cfg_reg + 4);
93
        outb(value, cs->hw.avm.isac + (offset & 0xf));
94
}
95
 
96
static void
97
ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size)
98
{
99
        outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
100
        insb(cs->hw.avm.isac, data, size);
101
}
102
 
103
static void
104
WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size)
105
{
106
        outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4);
107
        outsb(cs->hw.avm.isac, data, size);
108
}
109
 
110
static inline u_int
111
ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset)
112
{
113
        register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
114
        register u_int val;
115
 
116
        outl(idx, cs->hw.avm.cfg_reg + 4);
117
        val = inl(cs->hw.avm.isac + offset);
118
        return (val);
119
}
120
 
121
static inline void
122
WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value)
123
{
124
        register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
125
 
126
        outl(idx, cs->hw.avm.cfg_reg + 4);
127
        outl(value, cs->hw.avm.isac + offset);
128
}
129
 
130
static inline u_char
131
ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset)
132
{
133
        register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
134
        register u_char val;
135
 
136
        outb(idx, cs->hw.avm.cfg_reg + 4);
137
        val = inb(cs->hw.avm.isac + offset);
138
        return (val);
139
}
140
 
141
static inline void
142
WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
143
{
144
        register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1;
145
 
146
        outb(idx, cs->hw.avm.cfg_reg + 4);
147
        outb(value, cs->hw.avm.isac + offset);
148
}
149
 
150
static u_char
151
ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset)
152
{
153
        return(0xff & ReadHDLCPCI(cs, chan, offset));
154
}
155
 
156
static void
157
WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value)
158
{
159
        WriteHDLCPCI(cs, chan, offset, value);
160
}
161
 
162
static inline
163
struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
164
{
165
        if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
166
                return(&cs->bcs[0]);
167
        else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
168
                return(&cs->bcs[1]);
169
        else
170
                return(NULL);
171
}
172
 
173
static void
174
write_ctrl(struct BCState *bcs, int which) {
175
 
176
        if (bcs->cs->debug & L1_DEB_HSCX)
177
                debugl1(bcs->cs, "hdlc %c wr%x ctrl %x",
178
                        'A' + bcs->channel, which, bcs->hw.hdlc.ctrl.ctrl);
179
        if (bcs->cs->subtyp == AVM_FRITZ_PCI) {
180
                WriteHDLCPCI(bcs->cs, bcs->channel, HDLC_STATUS, bcs->hw.hdlc.ctrl.ctrl);
181
        } else {
182
                if (which & 4)
183
                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 2,
184
                                bcs->hw.hdlc.ctrl.sr.mode);
185
                if (which & 2)
186
                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS + 1,
187
                                bcs->hw.hdlc.ctrl.sr.xml);
188
                if (which & 1)
189
                        WriteHDLCPnP(bcs->cs, bcs->channel, HDLC_STATUS,
190
                                bcs->hw.hdlc.ctrl.sr.cmd);
191
        }
192
}
193
 
194
static void
195
modehdlc(struct BCState *bcs, int mode, int bc)
196
{
197
        struct IsdnCardState *cs = bcs->cs;
198
        int hdlc = bcs->channel;
199
 
200
        if (cs->debug & L1_DEB_HSCX)
201
                debugl1(cs, "hdlc %c mode %d --> %d ichan %d --> %d",
202
                        'A' + hdlc, bcs->mode, mode, hdlc, bc);
203
        bcs->hw.hdlc.ctrl.ctrl = 0;
204
        switch (mode) {
205
                case (-1): /* used for init */
206
                        bcs->mode = 1;
207
                        bcs->channel = bc;
208
                        bc = 0;
209
                case (L1_MODE_NULL):
210
                        if (bcs->mode == L1_MODE_NULL)
211
                                return;
212
                        bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
213
                        bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
214
                        write_ctrl(bcs, 5);
215
                        bcs->mode = L1_MODE_NULL;
216
                        bcs->channel = bc;
217
                        break;
218
                case (L1_MODE_TRANS):
219
                        bcs->mode = mode;
220
                        bcs->channel = bc;
221
                        bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
222
                        bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_TRANS;
223
                        write_ctrl(bcs, 5);
224
                        bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
225
                        write_ctrl(bcs, 1);
226
                        bcs->hw.hdlc.ctrl.sr.cmd = 0;
227
                        schedule_event(bcs, B_XMTBUFREADY);
228
                        break;
229
                case (L1_MODE_HDLC):
230
                        bcs->mode = mode;
231
                        bcs->channel = bc;
232
                        bcs->hw.hdlc.ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
233
                        bcs->hw.hdlc.ctrl.sr.mode = HDLC_MODE_ITF_FLG;
234
                        write_ctrl(bcs, 5);
235
                        bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS;
236
                        write_ctrl(bcs, 1);
237
                        bcs->hw.hdlc.ctrl.sr.cmd = 0;
238
                        schedule_event(bcs, B_XMTBUFREADY);
239
                        break;
240
        }
241
}
242
 
243
static inline void
244
hdlc_empty_fifo(struct BCState *bcs, int count)
245
{
246
        register u_int *ptr;
247
        u_char *p;
248
        u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1;
249
        int cnt=0;
250
        struct IsdnCardState *cs = bcs->cs;
251
 
252
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
253
                debugl1(cs, "hdlc_empty_fifo %d", count);
254
        if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) {
255
                if (cs->debug & L1_DEB_WARN)
256
                        debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
257
                return;
258
        }
259
        p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
260
        ptr = (u_int *)p;
261
        bcs->hw.hdlc.rcvidx += count;
262
        if (cs->subtyp == AVM_FRITZ_PCI) {
263
                outl(idx, cs->hw.avm.cfg_reg + 4);
264
                while (cnt < count) {
265
#ifdef __powerpc__
266
#ifdef CONFIG_APUS
267
                        *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
268
#else
269
                        *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE));
270
#endif /* CONFIG_APUS */
271
#else
272
                        *ptr++ = inl(cs->hw.avm.isac);
273
#endif /* __powerpc__ */
274
                        cnt += 4;
275
                }
276
        } else {
277
                outb(idx, cs->hw.avm.cfg_reg + 4);
278
                while (cnt < count) {
279
                        *p++ = inb(cs->hw.avm.isac);
280
                        cnt++;
281
                }
282
        }
283
        if (cs->debug & L1_DEB_HSCX_FIFO) {
284
                char *t = bcs->blog;
285
 
286
                if (cs->subtyp == AVM_FRITZ_PNP)
287
                        p = (u_char *) ptr;
288
                t += sprintf(t, "hdlc_empty_fifo %c cnt %d",
289
                             bcs->channel ? 'B' : 'A', count);
290
                QuickHex(t, p, count);
291
                debugl1(cs, bcs->blog);
292
        }
293
}
294
 
295
static inline void
296
hdlc_fill_fifo(struct BCState *bcs)
297
{
298
        struct IsdnCardState *cs = bcs->cs;
299
        int count, cnt =0;
300
        int fifo_size = 32;
301
        u_char *p;
302
        u_int *ptr;
303
 
304
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
305
                debugl1(cs, "hdlc_fill_fifo");
306
        if (!bcs->tx_skb)
307
                return;
308
        if (bcs->tx_skb->len <= 0)
309
                return;
310
 
311
        bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME;
312
        if (bcs->tx_skb->len > fifo_size) {
313
                count = fifo_size;
314
        } else {
315
                count = bcs->tx_skb->len;
316
                if (bcs->mode != L1_MODE_TRANS)
317
                        bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME;
318
        }
319
        if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
320
                debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
321
        p = bcs->tx_skb->data;
322
        ptr = (u_int *)p;
323
        skb_pull(bcs->tx_skb, count);
324
        bcs->tx_cnt -= count;
325
        bcs->hw.hdlc.count += count;
326
        bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
327
        write_ctrl(bcs, 3);  /* sets the correct index too */
328
        if (cs->subtyp == AVM_FRITZ_PCI) {
329
                while (cnt<count) {
330
#ifdef __powerpc__
331
#ifdef CONFIG_APUS
332
                        out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
333
#else
334
                        out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++);
335
#endif /* CONFIG_APUS */
336
#else
337
                        outl(*ptr++, cs->hw.avm.isac);
338
#endif /* __powerpc__ */
339
                        cnt += 4;
340
                }
341
        } else {
342
                while (cnt<count) {
343
                        outb(*p++, cs->hw.avm.isac);
344
                        cnt++;
345
                }
346
        }
347
        if (cs->debug & L1_DEB_HSCX_FIFO) {
348
                char *t = bcs->blog;
349
 
350
                if (cs->subtyp == AVM_FRITZ_PNP)
351
                        p = (u_char *) ptr;
352
                t += sprintf(t, "hdlc_fill_fifo %c cnt %d",
353
                             bcs->channel ? 'B' : 'A', count);
354
                QuickHex(t, p, count);
355
                debugl1(cs, bcs->blog);
356
        }
357
}
358
 
359
static void
360
HDLC_irq(struct BCState *bcs, u_int stat) {
361
        int len;
362
        struct sk_buff *skb;
363
 
364
        if (bcs->cs->debug & L1_DEB_HSCX)
365
                debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
366
        if (stat & HDLC_INT_RPR) {
367
                if (stat & HDLC_STAT_RDO) {
368
                        if (bcs->cs->debug & L1_DEB_HSCX)
369
                                debugl1(bcs->cs, "RDO");
370
                        else
371
                                debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat);
372
                        bcs->hw.hdlc.ctrl.sr.xml = 0;
373
                        bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_RRS;
374
                        write_ctrl(bcs, 1);
375
                        bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS;
376
                        write_ctrl(bcs, 1);
377
                        bcs->hw.hdlc.rcvidx = 0;
378
                } else {
379
                        if (!(len = (stat & HDLC_STAT_RML_MASK)>>8))
380
                                len = 32;
381
                        hdlc_empty_fifo(bcs, len);
382
                        if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
383
                                if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) ||
384
                                        (bcs->mode == L1_MODE_TRANS)) {
385
                                        if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx)))
386
                                                printk(KERN_WARNING "HDLC: receive out of memory\n");
387
                                        else {
388
                                                memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx),
389
                                                        bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx);
390
                                                skb_queue_tail(&bcs->rqueue, skb);
391
                                        }
392
                                        bcs->hw.hdlc.rcvidx = 0;
393
                                        schedule_event(bcs, B_RCVBUFREADY);
394
                                } else {
395
                                        if (bcs->cs->debug & L1_DEB_HSCX)
396
                                                debugl1(bcs->cs, "invalid frame");
397
                                        else
398
                                                debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat);
399
                                        bcs->hw.hdlc.rcvidx = 0;
400
                                }
401
                        }
402
                }
403
        }
404
        if (stat & HDLC_INT_XDU) {
405
                /* Here we lost an TX interrupt, so
406
                 * restart transmitting the whole frame.
407
                 */
408
                if (bcs->tx_skb) {
409
                        skb_push(bcs->tx_skb, bcs->hw.hdlc.count);
410
                        bcs->tx_cnt += bcs->hw.hdlc.count;
411
                        bcs->hw.hdlc.count = 0;
412
                        if (bcs->cs->debug & L1_DEB_WARN)
413
                                debugl1(bcs->cs, "ch%d XDU", bcs->channel);
414
                } else if (bcs->cs->debug & L1_DEB_WARN)
415
                        debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel);
416
                bcs->hw.hdlc.ctrl.sr.xml = 0;
417
                bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS;
418
                write_ctrl(bcs, 1);
419
                bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS;
420
                write_ctrl(bcs, 1);
421
                hdlc_fill_fifo(bcs);
422
        } else if (stat & HDLC_INT_XPR) {
423
                if (bcs->tx_skb) {
424
                        if (bcs->tx_skb->len) {
425
                                hdlc_fill_fifo(bcs);
426
                                return;
427
                        } else {
428
                                if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) &&
429
                                        (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
430
                                        u_long  flags;
431
                                        spin_lock_irqsave(&bcs->aclock, flags);
432
                                        bcs->ackcnt += bcs->hw.hdlc.count;
433
                                        spin_unlock_irqrestore(&bcs->aclock, flags);
434
                                        schedule_event(bcs, B_ACKPENDING);
435
                                }
436
                                dev_kfree_skb_irq(bcs->tx_skb);
437
                                bcs->hw.hdlc.count = 0;
438
                                bcs->tx_skb = NULL;
439
                        }
440
                }
441
                if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
442
                        bcs->hw.hdlc.count = 0;
443
                        test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
444
                        hdlc_fill_fifo(bcs);
445
                } else {
446
                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
447
                        schedule_event(bcs, B_XMTBUFREADY);
448
                }
449
        }
450
}
451
 
452
static inline void
453
HDLC_irq_main(struct IsdnCardState *cs)
454
{
455
        u_int stat;
456
        struct BCState *bcs;
457
 
458
        if (cs->subtyp == AVM_FRITZ_PCI) {
459
                stat = ReadHDLCPCI(cs, 0, HDLC_STATUS);
460
        } else {
461
                stat = ReadHDLCPnP(cs, 0, HDLC_STATUS);
462
                if (stat & HDLC_INT_RPR)
463
                        stat |= (ReadHDLCPnP(cs, 0, HDLC_STATUS+1))<<8;
464
        }
465
        if (stat & HDLC_INT_MASK) {
466
                if (!(bcs = Sel_BCS(cs, 0))) {
467
                        if (cs->debug)
468
                                debugl1(cs, "hdlc spurious channel 0 IRQ");
469
                } else
470
                        HDLC_irq(bcs, stat);
471
        }
472
        if (cs->subtyp == AVM_FRITZ_PCI) {
473
                stat = ReadHDLCPCI(cs, 1, HDLC_STATUS);
474
        } else {
475
                stat = ReadHDLCPnP(cs, 1, HDLC_STATUS);
476
                if (stat & HDLC_INT_RPR)
477
                        stat |= (ReadHDLCPnP(cs, 1, HDLC_STATUS+1))<<8;
478
        }
479
        if (stat & HDLC_INT_MASK) {
480
                if (!(bcs = Sel_BCS(cs, 1))) {
481
                        if (cs->debug)
482
                                debugl1(cs, "hdlc spurious channel 1 IRQ");
483
                } else
484
                        HDLC_irq(bcs, stat);
485
        }
486
}
487
 
488
static void
489
hdlc_l2l1(struct PStack *st, int pr, void *arg)
490
{
491
        struct BCState *bcs = st->l1.bcs;
492
        struct sk_buff *skb = arg;
493
        u_long flags;
494
 
495
        switch (pr) {
496
                case (PH_DATA | REQUEST):
497
                        spin_lock_irqsave(&bcs->cs->lock, flags);
498
                        if (bcs->tx_skb) {
499
                                skb_queue_tail(&bcs->squeue, skb);
500
                        } else {
501
                                bcs->tx_skb = skb;
502
                                test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
503
                                bcs->hw.hdlc.count = 0;
504
                                bcs->cs->BC_Send_Data(bcs);
505
                        }
506
                        spin_unlock_irqrestore(&bcs->cs->lock, flags);
507
                        break;
508
                case (PH_PULL | INDICATION):
509
                        spin_lock_irqsave(&bcs->cs->lock, flags);
510
                        if (bcs->tx_skb) {
511
                                printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n");
512
                        } else {
513
                                test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
514
                                bcs->tx_skb = skb;
515
                                bcs->hw.hdlc.count = 0;
516
                                bcs->cs->BC_Send_Data(bcs);
517
                        }
518
                        spin_unlock_irqrestore(&bcs->cs->lock, flags);
519
                        break;
520
                case (PH_PULL | REQUEST):
521
                        if (!bcs->tx_skb) {
522
                                test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
523
                                st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
524
                        } else
525
                                test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
526
                        break;
527
                case (PH_ACTIVATE | REQUEST):
528
                        spin_lock_irqsave(&bcs->cs->lock, flags);
529
                        test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
530
                        modehdlc(bcs, st->l1.mode, st->l1.bc);
531
                        spin_unlock_irqrestore(&bcs->cs->lock, flags);
532
                        l1_msg_b(st, pr, arg);
533
                        break;
534
                case (PH_DEACTIVATE | REQUEST):
535
                        l1_msg_b(st, pr, arg);
536
                        break;
537
                case (PH_DEACTIVATE | CONFIRM):
538
                        spin_lock_irqsave(&bcs->cs->lock, flags);
539
                        test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
540
                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
541
                        modehdlc(bcs, 0, st->l1.bc);
542
                        spin_unlock_irqrestore(&bcs->cs->lock, flags);
543
                        st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
544
                        break;
545
        }
546
}
547
 
548
static void
549
close_hdlcstate(struct BCState *bcs)
550
{
551
        modehdlc(bcs, 0, 0);
552
        if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
553
                kfree(bcs->hw.hdlc.rcvbuf);
554
                bcs->hw.hdlc.rcvbuf = NULL;
555
                kfree(bcs->blog);
556
                bcs->blog = NULL;
557
                skb_queue_purge(&bcs->rqueue);
558
                skb_queue_purge(&bcs->squeue);
559
                if (bcs->tx_skb) {
560
                        dev_kfree_skb_any(bcs->tx_skb);
561
                        bcs->tx_skb = NULL;
562
                        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
563
                }
564
        }
565
}
566
 
567
static int
568
open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
569
{
570
        if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
571
                if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) {
572
                        printk(KERN_WARNING
573
                               "HiSax: No memory for hdlc.rcvbuf\n");
574
                        return (1);
575
                }
576
                if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) {
577
                        printk(KERN_WARNING
578
                                "HiSax: No memory for bcs->blog\n");
579
                        test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
580
                        kfree(bcs->hw.hdlc.rcvbuf);
581
                        bcs->hw.hdlc.rcvbuf = NULL;
582
                        return (2);
583
                }
584
                skb_queue_head_init(&bcs->rqueue);
585
                skb_queue_head_init(&bcs->squeue);
586
        }
587
        bcs->tx_skb = NULL;
588
        test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
589
        bcs->event = 0;
590
        bcs->hw.hdlc.rcvidx = 0;
591
        bcs->tx_cnt = 0;
592
        return (0);
593
}
594
 
595
static int
596
setstack_hdlc(struct PStack *st, struct BCState *bcs)
597
{
598
        bcs->channel = st->l1.bc;
599
        if (open_hdlcstate(st->l1.hardware, bcs))
600
                return (-1);
601
        st->l1.bcs = bcs;
602
        st->l2.l2l1 = hdlc_l2l1;
603
        setstack_manager(st);
604
        bcs->st = st;
605
        setstack_l1_B(st);
606
        return (0);
607
}
608
 
609
#if 0
610
void __init
611
clear_pending_hdlc_ints(struct IsdnCardState *cs)
612
{
613
        u_int val;
614
 
615
        if (cs->subtyp == AVM_FRITZ_PCI) {
616
                val = ReadHDLCPCI(cs, 0, HDLC_STATUS);
617
                debugl1(cs, "HDLC 1 STA %x", val);
618
                val = ReadHDLCPCI(cs, 1, HDLC_STATUS);
619
                debugl1(cs, "HDLC 2 STA %x", val);
620
        } else {
621
                val = ReadHDLCPnP(cs, 0, HDLC_STATUS);
622
                debugl1(cs, "HDLC 1 STA %x", val);
623
                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 1);
624
                debugl1(cs, "HDLC 1 RML %x", val);
625
                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 2);
626
                debugl1(cs, "HDLC 1 MODE %x", val);
627
                val = ReadHDLCPnP(cs, 0, HDLC_STATUS + 3);
628
                debugl1(cs, "HDLC 1 VIN %x", val);
629
                val = ReadHDLCPnP(cs, 1, HDLC_STATUS);
630
                debugl1(cs, "HDLC 2 STA %x", val);
631
                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 1);
632
                debugl1(cs, "HDLC 2 RML %x", val);
633
                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 2);
634
                debugl1(cs, "HDLC 2 MODE %x", val);
635
                val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3);
636
                debugl1(cs, "HDLC 2 VIN %x", val);
637
        }
638
}
639
#endif  /*  0  */
640
 
641
static void
642
inithdlc(struct IsdnCardState *cs)
643
{
644
        cs->bcs[0].BC_SetStack = setstack_hdlc;
645
        cs->bcs[1].BC_SetStack = setstack_hdlc;
646
        cs->bcs[0].BC_Close = close_hdlcstate;
647
        cs->bcs[1].BC_Close = close_hdlcstate;
648
        modehdlc(cs->bcs, -1, 0);
649
        modehdlc(cs->bcs + 1, -1, 1);
650
}
651
 
652
static irqreturn_t
653
avm_pcipnp_interrupt(int intno, void *dev_id)
654
{
655
        struct IsdnCardState *cs = dev_id;
656
        u_long flags;
657
        u_char val;
658
        u_char sval;
659
 
660
        spin_lock_irqsave(&cs->lock, flags);
661
        sval = inb(cs->hw.avm.cfg_reg + 2);
662
        if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) {
663
                /* possible a shared  IRQ reqest */
664
                spin_unlock_irqrestore(&cs->lock, flags);
665
                return IRQ_NONE;
666
        }
667
        if (!(sval & AVM_STATUS0_IRQ_ISAC)) {
668
                val = ReadISAC(cs, ISAC_ISTA);
669
                isac_interrupt(cs, val);
670
        }
671
        if (!(sval & AVM_STATUS0_IRQ_HDLC)) {
672
                HDLC_irq_main(cs);
673
        }
674
        WriteISAC(cs, ISAC_MASK, 0xFF);
675
        WriteISAC(cs, ISAC_MASK, 0x0);
676
        spin_unlock_irqrestore(&cs->lock, flags);
677
        return IRQ_HANDLED;
678
}
679
 
680
static void
681
reset_avmpcipnp(struct IsdnCardState *cs)
682
{
683
        printk(KERN_INFO "AVM PCI/PnP: reset\n");
684
        outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2);
685
        mdelay(10);
686
        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
687
        outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3);
688
        mdelay(10);
689
        printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3));
690
}
691
 
692
static int
693
AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
694
{
695
        u_long flags;
696
 
697
        switch (mt) {
698
                case CARD_RESET:
699
                        spin_lock_irqsave(&cs->lock, flags);
700
                        reset_avmpcipnp(cs);
701
                        spin_unlock_irqrestore(&cs->lock, flags);
702
                        return(0);
703
                case CARD_RELEASE:
704
                        outb(0, cs->hw.avm.cfg_reg + 2);
705
                        release_region(cs->hw.avm.cfg_reg, 32);
706
                        return(0);
707
                case CARD_INIT:
708
                        spin_lock_irqsave(&cs->lock, flags);
709
                        reset_avmpcipnp(cs);
710
                        clear_pending_isac_ints(cs);
711
                        initisac(cs);
712
                        inithdlc(cs);
713
                        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER,
714
                                cs->hw.avm.cfg_reg + 2);
715
                        WriteISAC(cs, ISAC_MASK, 0);
716
                        outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
717
                                AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2);
718
                        /* RESET Receiver and Transmitter */
719
                        WriteISAC(cs, ISAC_CMDR, 0x41);
720
                        spin_unlock_irqrestore(&cs->lock, flags);
721
                        return(0);
722
                case CARD_TEST:
723
                        return(0);
724
        }
725
        return(0);
726
}
727
 
728
static int __devinit avm_setup_rest(struct IsdnCardState *cs)
729
{
730
        u_int val, ver;
731
 
732
        cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
733
        if (!request_region(cs->hw.avm.cfg_reg, 32,
734
                (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) {
735
                printk(KERN_WARNING
736
                       "HiSax: Fritz!PCI/PNP config port %x-%x already in use\n",
737
                       cs->hw.avm.cfg_reg,
738
                       cs->hw.avm.cfg_reg + 31);
739
                return (0);
740
        }
741
        switch (cs->subtyp) {
742
          case AVM_FRITZ_PCI:
743
                val = inl(cs->hw.avm.cfg_reg);
744
                printk(KERN_INFO "AVM PCI: stat %#x\n", val);
745
                printk(KERN_INFO "AVM PCI: Class %X Rev %d\n",
746
                        val & 0xff, (val>>8) & 0xff);
747
                cs->BC_Read_Reg = &ReadHDLC_s;
748
                cs->BC_Write_Reg = &WriteHDLC_s;
749
                break;
750
          case AVM_FRITZ_PNP:
751
                val = inb(cs->hw.avm.cfg_reg);
752
                ver = inb(cs->hw.avm.cfg_reg + 1);
753
                printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver);
754
                cs->BC_Read_Reg = &ReadHDLCPnP;
755
                cs->BC_Write_Reg = &WriteHDLCPnP;
756
                break;
757
          default:
758
                printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp);
759
                return(0);
760
        }
761
        printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n",
762
                (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
763
                cs->irq, cs->hw.avm.cfg_reg);
764
 
765
        setup_isac(cs);
766
        cs->readisac = &ReadISAC;
767
        cs->writeisac = &WriteISAC;
768
        cs->readisacfifo = &ReadISACfifo;
769
        cs->writeisacfifo = &WriteISACfifo;
770
        cs->BC_Send_Data = &hdlc_fill_fifo;
771
        cs->cardmsg = &AVM_card_msg;
772
        cs->irq_func = &avm_pcipnp_interrupt;
773
        cs->writeisac(cs, ISAC_MASK, 0xFF);
774
        ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:");
775
        return (1);
776
}
777
 
778
#ifndef __ISAPNP__
779
 
780
static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
781
{
782
        return(1);      /* no-op: success */
783
}
784
 
785
#else
786
 
787
static struct pnp_card *pnp_avm_c __devinitdata = NULL;
788
 
789
static int __devinit avm_pnp_setup(struct IsdnCardState *cs)
790
{
791
        struct pnp_dev *pnp_avm_d = NULL;
792
 
793
        if (!isapnp_present())
794
                return(1);      /* no-op: success */
795
 
796
        if ((pnp_avm_c = pnp_find_card(
797
                ISAPNP_VENDOR('A', 'V', 'M'),
798
                ISAPNP_FUNCTION(0x0900), pnp_avm_c))) {
799
                if ((pnp_avm_d = pnp_find_dev(pnp_avm_c,
800
                        ISAPNP_VENDOR('A', 'V', 'M'),
801
                        ISAPNP_FUNCTION(0x0900), pnp_avm_d))) {
802
                        int err;
803
 
804
                        pnp_disable_dev(pnp_avm_d);
805
                        err = pnp_activate_dev(pnp_avm_d);
806
                        if (err<0) {
807
                                printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n",
808
                                        __FUNCTION__, err);
809
                                return(0);
810
                        }
811
                        cs->hw.avm.cfg_reg =
812
                                pnp_port_start(pnp_avm_d, 0);
813
                        cs->irq = pnp_irq(pnp_avm_d, 0);
814
                        if (!cs->irq) {
815
                                printk(KERN_ERR "FritzPnP:No IRQ\n");
816
                                return(0);
817
                        }
818
                        if (!cs->hw.avm.cfg_reg) {
819
                                printk(KERN_ERR "FritzPnP:No IO address\n");
820
                                return(0);
821
                        }
822
                        cs->subtyp = AVM_FRITZ_PNP;
823
 
824
                        return (2);     /* goto 'ready' label */
825
                }
826
        }
827
 
828
        return (1);
829
}
830
 
831
#endif /* __ISAPNP__ */
832
 
833
#ifndef CONFIG_PCI_LEGACY
834
 
835
static int __devinit avm_pci_setup(struct IsdnCardState *cs)
836
{
837
        return(1);      /* no-op: success */
838
}
839
 
840
#else
841
 
842
static struct pci_dev *dev_avm __devinitdata = NULL;
843
 
844
static int __devinit avm_pci_setup(struct IsdnCardState *cs)
845
{
846
        if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM,
847
                PCI_DEVICE_ID_AVM_A1, dev_avm))) {
848
 
849
                if (pci_enable_device(dev_avm))
850
                        return(0);
851
 
852
                cs->irq = dev_avm->irq;
853
                if (!cs->irq) {
854
                        printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n");
855
                        return(0);
856
                }
857
 
858
                cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
859
                if (!cs->hw.avm.cfg_reg) {
860
                        printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
861
                        return(0);
862
                }
863
 
864
                cs->subtyp = AVM_FRITZ_PCI;
865
        } else {
866
                printk(KERN_WARNING "FritzPCI: No PCI card found\n");
867
                return(0);
868
        }
869
 
870
        cs->irq_flags |= IRQF_SHARED;
871
 
872
        return (1);
873
}
874
 
875
#endif /* CONFIG_PCI_LEGACY */
876
 
877
int __devinit
878
setup_avm_pcipnp(struct IsdnCard *card)
879
{
880
        struct IsdnCardState *cs = card->cs;
881
        char tmp[64];
882
        int rc;
883
 
884
        strcpy(tmp, avm_pci_rev);
885
        printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp));
886
 
887
        if (cs->typ != ISDN_CTYPE_FRITZPCI)
888
                return (0);
889
 
890
        if (card->para[1]) {
891
                /* old manual method */
892
                cs->hw.avm.cfg_reg = card->para[1];
893
                cs->irq = card->para[0];
894
                cs->subtyp = AVM_FRITZ_PNP;
895
                goto ready;
896
        }
897
 
898
        rc = avm_pnp_setup(cs);
899
        if (rc < 1)
900
                return (0);
901
        if (rc == 2)
902
                goto ready;
903
 
904
        rc = avm_pci_setup(cs);
905
        if (rc < 1)
906
                return (0);
907
 
908
ready:
909
        return avm_setup_rest(cs);
910
}

powered by: WebSVN 2.1.0

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