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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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