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