1 /* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $
3 * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * Thanks to AVM, Berlin for information
15 #include <linux/config.h>
16 #include <linux/init.h>
20 #include <linux/pci.h>
21 #include <linux/isapnp.h>
22 #include <linux/interrupt.h>
24 extern const char *CardType
[];
25 static const char *avm_pci_rev
= "$Revision: 1.29.2.4 $";
27 #define AVM_FRITZ_PCI 1
28 #define AVM_FRITZ_PNP 2
31 #define HDLC_STATUS 0x4
33 #define AVM_HDLC_1 0x00
34 #define AVM_HDLC_2 0x01
35 #define AVM_ISAC_FIFO 0x02
36 #define AVM_ISAC_REG_LOW 0x04
37 #define AVM_ISAC_REG_HIGH 0x06
39 #define AVM_STATUS0_IRQ_ISAC 0x01
40 #define AVM_STATUS0_IRQ_HDLC 0x02
41 #define AVM_STATUS0_IRQ_TIMER 0x04
42 #define AVM_STATUS0_IRQ_MASK 0x07
44 #define AVM_STATUS0_RESET 0x01
45 #define AVM_STATUS0_DIS_TIMER 0x02
46 #define AVM_STATUS0_RES_TIMER 0x04
47 #define AVM_STATUS0_ENA_IRQ 0x08
48 #define AVM_STATUS0_TESTBIT 0x10
50 #define AVM_STATUS1_INT_SEL 0x0f
51 #define AVM_STATUS1_ENA_IOM 0x80
53 #define HDLC_MODE_ITF_FLG 0x01
54 #define HDLC_MODE_TRANS 0x02
55 #define HDLC_MODE_CCR_7 0x04
56 #define HDLC_MODE_CCR_16 0x08
57 #define HDLC_MODE_TESTLOOP 0x80
59 #define HDLC_INT_XPR 0x80
60 #define HDLC_INT_XDU 0x40
61 #define HDLC_INT_RPR 0x20
62 #define HDLC_INT_MASK 0xE0
64 #define HDLC_STAT_RME 0x01
65 #define HDLC_STAT_RDO 0x10
66 #define HDLC_STAT_CRCVFRRAB 0x0E
67 #define HDLC_STAT_CRCVFR 0x06
68 #define HDLC_STAT_RML_MASK 0x3f00
70 #define HDLC_CMD_XRS 0x80
71 #define HDLC_CMD_XME 0x01
72 #define HDLC_CMD_RRS 0x20
73 #define HDLC_CMD_XML_MASK 0x3f00
76 /* Interface functions */
79 ReadISAC(struct IsdnCardState
*cs
, u_char offset
)
81 register u_char idx
= (offset
> 0x2f) ? AVM_ISAC_REG_HIGH
: AVM_ISAC_REG_LOW
;
84 outb(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
85 val
= inb(cs
->hw
.avm
.isac
+ (offset
& 0xf));
90 WriteISAC(struct IsdnCardState
*cs
, u_char offset
, u_char value
)
92 register u_char idx
= (offset
> 0x2f) ? AVM_ISAC_REG_HIGH
: AVM_ISAC_REG_LOW
;
94 outb(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
95 outb(value
, cs
->hw
.avm
.isac
+ (offset
& 0xf));
99 ReadISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
101 outb(AVM_ISAC_FIFO
, cs
->hw
.avm
.cfg_reg
+ 4);
102 insb(cs
->hw
.avm
.isac
, data
, size
);
106 WriteISACfifo(struct IsdnCardState
*cs
, u_char
* data
, int size
)
108 outb(AVM_ISAC_FIFO
, cs
->hw
.avm
.cfg_reg
+ 4);
109 outsb(cs
->hw
.avm
.isac
, data
, size
);
113 ReadHDLCPCI(struct IsdnCardState
*cs
, int chan
, u_char offset
)
115 register u_int idx
= chan
? AVM_HDLC_2
: AVM_HDLC_1
;
118 outl(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
119 val
= inl(cs
->hw
.avm
.isac
+ offset
);
124 WriteHDLCPCI(struct IsdnCardState
*cs
, int chan
, u_char offset
, u_int value
)
126 register u_int idx
= chan
? AVM_HDLC_2
: AVM_HDLC_1
;
128 outl(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
129 outl(value
, cs
->hw
.avm
.isac
+ offset
);
133 ReadHDLCPnP(struct IsdnCardState
*cs
, int chan
, u_char offset
)
135 register u_char idx
= chan
? AVM_HDLC_2
: AVM_HDLC_1
;
138 outb(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
139 val
= inb(cs
->hw
.avm
.isac
+ offset
);
144 WriteHDLCPnP(struct IsdnCardState
*cs
, int chan
, u_char offset
, u_char value
)
146 register u_char idx
= chan
? AVM_HDLC_2
: AVM_HDLC_1
;
148 outb(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
149 outb(value
, cs
->hw
.avm
.isac
+ offset
);
153 ReadHDLC_s(struct IsdnCardState
*cs
, int chan
, u_char offset
)
155 return(0xff & ReadHDLCPCI(cs
, chan
, offset
));
159 WriteHDLC_s(struct IsdnCardState
*cs
, int chan
, u_char offset
, u_char value
)
161 WriteHDLCPCI(cs
, chan
, offset
, value
);
165 struct BCState
*Sel_BCS(struct IsdnCardState
*cs
, int channel
)
167 if (cs
->bcs
[0].mode
&& (cs
->bcs
[0].channel
== channel
))
169 else if (cs
->bcs
[1].mode
&& (cs
->bcs
[1].channel
== channel
))
176 write_ctrl(struct BCState
*bcs
, int which
) {
178 if (bcs
->cs
->debug
& L1_DEB_HSCX
)
179 debugl1(bcs
->cs
, "hdlc %c wr%x ctrl %x",
180 'A' + bcs
->channel
, which
, bcs
->hw
.hdlc
.ctrl
.ctrl
);
181 if (bcs
->cs
->subtyp
== AVM_FRITZ_PCI
) {
182 WriteHDLCPCI(bcs
->cs
, bcs
->channel
, HDLC_STATUS
, bcs
->hw
.hdlc
.ctrl
.ctrl
);
185 WriteHDLCPnP(bcs
->cs
, bcs
->channel
, HDLC_STATUS
+ 2,
186 bcs
->hw
.hdlc
.ctrl
.sr
.mode
);
188 WriteHDLCPnP(bcs
->cs
, bcs
->channel
, HDLC_STATUS
+ 1,
189 bcs
->hw
.hdlc
.ctrl
.sr
.xml
);
191 WriteHDLCPnP(bcs
->cs
, bcs
->channel
, HDLC_STATUS
,
192 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
);
197 modehdlc(struct BCState
*bcs
, int mode
, int bc
)
199 struct IsdnCardState
*cs
= bcs
->cs
;
200 int hdlc
= bcs
->channel
;
202 if (cs
->debug
& L1_DEB_HSCX
)
203 debugl1(cs
, "hdlc %c mode %d --> %d ichan %d --> %d",
204 'A' + hdlc
, bcs
->mode
, mode
, hdlc
, bc
);
205 bcs
->hw
.hdlc
.ctrl
.ctrl
= 0;
207 case (-1): /* used for init */
212 if (bcs
->mode
== L1_MODE_NULL
)
214 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= HDLC_CMD_XRS
| HDLC_CMD_RRS
;
215 bcs
->hw
.hdlc
.ctrl
.sr
.mode
= HDLC_MODE_TRANS
;
217 bcs
->mode
= L1_MODE_NULL
;
220 case (L1_MODE_TRANS
):
223 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= HDLC_CMD_XRS
| HDLC_CMD_RRS
;
224 bcs
->hw
.hdlc
.ctrl
.sr
.mode
= HDLC_MODE_TRANS
;
226 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= HDLC_CMD_XRS
;
228 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= 0;
229 schedule_event(bcs
, B_XMTBUFREADY
);
234 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= HDLC_CMD_XRS
| HDLC_CMD_RRS
;
235 bcs
->hw
.hdlc
.ctrl
.sr
.mode
= HDLC_MODE_ITF_FLG
;
237 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= HDLC_CMD_XRS
;
239 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
= 0;
240 schedule_event(bcs
, B_XMTBUFREADY
);
246 hdlc_empty_fifo(struct BCState
*bcs
, int count
)
250 u_char idx
= bcs
->channel
? AVM_HDLC_2
: AVM_HDLC_1
;
252 struct IsdnCardState
*cs
= bcs
->cs
;
254 if ((cs
->debug
& L1_DEB_HSCX
) && !(cs
->debug
& L1_DEB_HSCX_FIFO
))
255 debugl1(cs
, "hdlc_empty_fifo %d", count
);
256 if (bcs
->hw
.hdlc
.rcvidx
+ count
> HSCX_BUFMAX
) {
257 if (cs
->debug
& L1_DEB_WARN
)
258 debugl1(cs
, "hdlc_empty_fifo: incoming packet too large");
261 p
= bcs
->hw
.hdlc
.rcvbuf
+ bcs
->hw
.hdlc
.rcvidx
;
263 bcs
->hw
.hdlc
.rcvidx
+= count
;
264 if (cs
->subtyp
== AVM_FRITZ_PCI
) {
265 outl(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
266 while (cnt
< count
) {
269 *ptr
++ = in_le32((unsigned *)(cs
->hw
.avm
.isac
+_IO_BASE
));
271 *ptr
++ = in_be32((unsigned *)(cs
->hw
.avm
.isac
+_IO_BASE
));
272 #endif /* CONFIG_APUS */
274 *ptr
++ = inl(cs
->hw
.avm
.isac
);
275 #endif /* __powerpc__ */
279 outb(idx
, cs
->hw
.avm
.cfg_reg
+ 4);
280 while (cnt
< count
) {
281 *p
++ = inb(cs
->hw
.avm
.isac
);
285 if (cs
->debug
& L1_DEB_HSCX_FIFO
) {
288 if (cs
->subtyp
== AVM_FRITZ_PNP
)
290 t
+= sprintf(t
, "hdlc_empty_fifo %c cnt %d",
291 bcs
->channel
? 'B' : 'A', count
);
292 QuickHex(t
, p
, count
);
293 debugl1(cs
, bcs
->blog
);
298 hdlc_fill_fifo(struct BCState
*bcs
)
300 struct IsdnCardState
*cs
= bcs
->cs
;
306 if ((cs
->debug
& L1_DEB_HSCX
) && !(cs
->debug
& L1_DEB_HSCX_FIFO
))
307 debugl1(cs
, "hdlc_fill_fifo");
310 if (bcs
->tx_skb
->len
<= 0)
313 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
&= ~HDLC_CMD_XME
;
314 if (bcs
->tx_skb
->len
> fifo_size
) {
317 count
= bcs
->tx_skb
->len
;
318 if (bcs
->mode
!= L1_MODE_TRANS
)
319 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
|= HDLC_CMD_XME
;
321 if ((cs
->debug
& L1_DEB_HSCX
) && !(cs
->debug
& L1_DEB_HSCX_FIFO
))
322 debugl1(cs
, "hdlc_fill_fifo %d/%ld", count
, bcs
->tx_skb
->len
);
323 p
= bcs
->tx_skb
->data
;
325 skb_pull(bcs
->tx_skb
, count
);
326 bcs
->tx_cnt
-= count
;
327 bcs
->hw
.hdlc
.count
+= count
;
328 bcs
->hw
.hdlc
.ctrl
.sr
.xml
= ((count
== fifo_size
) ? 0 : count
);
329 write_ctrl(bcs
, 3); /* sets the correct index too */
330 if (cs
->subtyp
== AVM_FRITZ_PCI
) {
334 out_le32((unsigned *)(cs
->hw
.avm
.isac
+_IO_BASE
), *ptr
++);
336 out_be32((unsigned *)(cs
->hw
.avm
.isac
+_IO_BASE
), *ptr
++);
337 #endif /* CONFIG_APUS */
339 outl(*ptr
++, cs
->hw
.avm
.isac
);
340 #endif /* __powerpc__ */
345 outb(*p
++, cs
->hw
.avm
.isac
);
349 if (cs
->debug
& L1_DEB_HSCX_FIFO
) {
352 if (cs
->subtyp
== AVM_FRITZ_PNP
)
354 t
+= sprintf(t
, "hdlc_fill_fifo %c cnt %d",
355 bcs
->channel
? 'B' : 'A', count
);
356 QuickHex(t
, p
, count
);
357 debugl1(cs
, bcs
->blog
);
362 HDLC_irq(struct BCState
*bcs
, u_int stat
) {
366 if (bcs
->cs
->debug
& L1_DEB_HSCX
)
367 debugl1(bcs
->cs
, "ch%d stat %#x", bcs
->channel
, stat
);
368 if (stat
& HDLC_INT_RPR
) {
369 if (stat
& HDLC_STAT_RDO
) {
370 if (bcs
->cs
->debug
& L1_DEB_HSCX
)
371 debugl1(bcs
->cs
, "RDO");
373 debugl1(bcs
->cs
, "ch%d stat %#x", bcs
->channel
, stat
);
374 bcs
->hw
.hdlc
.ctrl
.sr
.xml
= 0;
375 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
|= HDLC_CMD_RRS
;
377 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
&= ~HDLC_CMD_RRS
;
379 bcs
->hw
.hdlc
.rcvidx
= 0;
381 if (!(len
= (stat
& HDLC_STAT_RML_MASK
)>>8))
383 hdlc_empty_fifo(bcs
, len
);
384 if ((stat
& HDLC_STAT_RME
) || (bcs
->mode
== L1_MODE_TRANS
)) {
385 if (((stat
& HDLC_STAT_CRCVFRRAB
)==HDLC_STAT_CRCVFR
) ||
386 (bcs
->mode
== L1_MODE_TRANS
)) {
387 if (!(skb
= dev_alloc_skb(bcs
->hw
.hdlc
.rcvidx
)))
388 printk(KERN_WARNING
"HDLC: receive out of memory\n");
390 memcpy(skb_put(skb
, bcs
->hw
.hdlc
.rcvidx
),
391 bcs
->hw
.hdlc
.rcvbuf
, bcs
->hw
.hdlc
.rcvidx
);
392 skb_queue_tail(&bcs
->rqueue
, skb
);
394 bcs
->hw
.hdlc
.rcvidx
= 0;
395 schedule_event(bcs
, B_RCVBUFREADY
);
397 if (bcs
->cs
->debug
& L1_DEB_HSCX
)
398 debugl1(bcs
->cs
, "invalid frame");
400 debugl1(bcs
->cs
, "ch%d invalid frame %#x", bcs
->channel
, stat
);
401 bcs
->hw
.hdlc
.rcvidx
= 0;
406 if (stat
& HDLC_INT_XDU
) {
407 /* Here we lost an TX interrupt, so
408 * restart transmitting the whole frame.
411 skb_push(bcs
->tx_skb
, bcs
->hw
.hdlc
.count
);
412 bcs
->tx_cnt
+= bcs
->hw
.hdlc
.count
;
413 bcs
->hw
.hdlc
.count
= 0;
414 if (bcs
->cs
->debug
& L1_DEB_WARN
)
415 debugl1(bcs
->cs
, "ch%d XDU", bcs
->channel
);
416 } else if (bcs
->cs
->debug
& L1_DEB_WARN
)
417 debugl1(bcs
->cs
, "ch%d XDU without skb", bcs
->channel
);
418 bcs
->hw
.hdlc
.ctrl
.sr
.xml
= 0;
419 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
|= HDLC_CMD_XRS
;
421 bcs
->hw
.hdlc
.ctrl
.sr
.cmd
&= ~HDLC_CMD_XRS
;
424 } else if (stat
& HDLC_INT_XPR
) {
426 if (bcs
->tx_skb
->len
) {
430 if (test_bit(FLG_LLI_L1WAKEUP
,&bcs
->st
->lli
.flag
) &&
431 (PACKET_NOACK
!= bcs
->tx_skb
->pkt_type
)) {
433 spin_lock_irqsave(&bcs
->aclock
, flags
);
434 bcs
->ackcnt
+= bcs
->hw
.hdlc
.count
;
435 spin_unlock_irqrestore(&bcs
->aclock
, flags
);
436 schedule_event(bcs
, B_ACKPENDING
);
438 dev_kfree_skb_irq(bcs
->tx_skb
);
439 bcs
->hw
.hdlc
.count
= 0;
443 if ((bcs
->tx_skb
= skb_dequeue(&bcs
->squeue
))) {
444 bcs
->hw
.hdlc
.count
= 0;
445 test_and_set_bit(BC_FLG_BUSY
, &bcs
->Flag
);
448 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
449 schedule_event(bcs
, B_XMTBUFREADY
);
455 HDLC_irq_main(struct IsdnCardState
*cs
)
460 if (cs
->subtyp
== AVM_FRITZ_PCI
) {
461 stat
= ReadHDLCPCI(cs
, 0, HDLC_STATUS
);
463 stat
= ReadHDLCPnP(cs
, 0, HDLC_STATUS
);
464 if (stat
& HDLC_INT_RPR
)
465 stat
|= (ReadHDLCPnP(cs
, 0, HDLC_STATUS
+1))<<8;
467 if (stat
& HDLC_INT_MASK
) {
468 if (!(bcs
= Sel_BCS(cs
, 0))) {
470 debugl1(cs
, "hdlc spurious channel 0 IRQ");
474 if (cs
->subtyp
== AVM_FRITZ_PCI
) {
475 stat
= ReadHDLCPCI(cs
, 1, HDLC_STATUS
);
477 stat
= ReadHDLCPnP(cs
, 1, HDLC_STATUS
);
478 if (stat
& HDLC_INT_RPR
)
479 stat
|= (ReadHDLCPnP(cs
, 1, HDLC_STATUS
+1))<<8;
481 if (stat
& HDLC_INT_MASK
) {
482 if (!(bcs
= Sel_BCS(cs
, 1))) {
484 debugl1(cs
, "hdlc spurious channel 1 IRQ");
491 hdlc_l2l1(struct PStack
*st
, int pr
, void *arg
)
493 struct BCState
*bcs
= st
->l1
.bcs
;
494 struct sk_buff
*skb
= arg
;
498 case (PH_DATA
| REQUEST
):
499 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
501 skb_queue_tail(&bcs
->squeue
, skb
);
504 test_and_set_bit(BC_FLG_BUSY
, &bcs
->Flag
);
505 bcs
->hw
.hdlc
.count
= 0;
506 bcs
->cs
->BC_Send_Data(bcs
);
508 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
510 case (PH_PULL
| INDICATION
):
511 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
513 printk(KERN_WARNING
"hdlc_l2l1: this shouldn't happen\n");
515 test_and_set_bit(BC_FLG_BUSY
, &bcs
->Flag
);
517 bcs
->hw
.hdlc
.count
= 0;
518 bcs
->cs
->BC_Send_Data(bcs
);
520 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
522 case (PH_PULL
| REQUEST
):
524 test_and_clear_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
525 st
->l1
.l1l2(st
, PH_PULL
| CONFIRM
, NULL
);
527 test_and_set_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
529 case (PH_ACTIVATE
| REQUEST
):
530 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
531 test_and_set_bit(BC_FLG_ACTIV
, &bcs
->Flag
);
532 modehdlc(bcs
, st
->l1
.mode
, st
->l1
.bc
);
533 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
534 l1_msg_b(st
, pr
, arg
);
536 case (PH_DEACTIVATE
| REQUEST
):
537 l1_msg_b(st
, pr
, arg
);
539 case (PH_DEACTIVATE
| CONFIRM
):
540 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
541 test_and_clear_bit(BC_FLG_ACTIV
, &bcs
->Flag
);
542 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
543 modehdlc(bcs
, 0, st
->l1
.bc
);
544 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
545 st
->l1
.l1l2(st
, PH_DEACTIVATE
| CONFIRM
, NULL
);
551 close_hdlcstate(struct BCState
*bcs
)
554 if (test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
555 if (bcs
->hw
.hdlc
.rcvbuf
) {
556 kfree(bcs
->hw
.hdlc
.rcvbuf
);
557 bcs
->hw
.hdlc
.rcvbuf
= NULL
;
563 skb_queue_purge(&bcs
->rqueue
);
564 skb_queue_purge(&bcs
->squeue
);
566 dev_kfree_skb_any(bcs
->tx_skb
);
568 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
574 open_hdlcstate(struct IsdnCardState
*cs
, struct BCState
*bcs
)
576 if (!test_and_set_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
577 if (!(bcs
->hw
.hdlc
.rcvbuf
= kmalloc(HSCX_BUFMAX
, GFP_ATOMIC
))) {
579 "HiSax: No memory for hdlc.rcvbuf\n");
582 if (!(bcs
->blog
= kmalloc(MAX_BLOG_SPACE
, GFP_ATOMIC
))) {
584 "HiSax: No memory for bcs->blog\n");
585 test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
);
586 kfree(bcs
->hw
.hdlc
.rcvbuf
);
587 bcs
->hw
.hdlc
.rcvbuf
= NULL
;
590 skb_queue_head_init(&bcs
->rqueue
);
591 skb_queue_head_init(&bcs
->squeue
);
594 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
596 bcs
->hw
.hdlc
.rcvidx
= 0;
602 setstack_hdlc(struct PStack
*st
, struct BCState
*bcs
)
604 bcs
->channel
= st
->l1
.bc
;
605 if (open_hdlcstate(st
->l1
.hardware
, bcs
))
608 st
->l2
.l2l1
= hdlc_l2l1
;
609 setstack_manager(st
);
616 clear_pending_hdlc_ints(struct IsdnCardState
*cs
)
620 if (cs
->subtyp
== AVM_FRITZ_PCI
) {
621 val
= ReadHDLCPCI(cs
, 0, HDLC_STATUS
);
622 debugl1(cs
, "HDLC 1 STA %x", val
);
623 val
= ReadHDLCPCI(cs
, 1, HDLC_STATUS
);
624 debugl1(cs
, "HDLC 2 STA %x", val
);
626 val
= ReadHDLCPnP(cs
, 0, HDLC_STATUS
);
627 debugl1(cs
, "HDLC 1 STA %x", val
);
628 val
= ReadHDLCPnP(cs
, 0, HDLC_STATUS
+ 1);
629 debugl1(cs
, "HDLC 1 RML %x", val
);
630 val
= ReadHDLCPnP(cs
, 0, HDLC_STATUS
+ 2);
631 debugl1(cs
, "HDLC 1 MODE %x", val
);
632 val
= ReadHDLCPnP(cs
, 0, HDLC_STATUS
+ 3);
633 debugl1(cs
, "HDLC 1 VIN %x", val
);
634 val
= ReadHDLCPnP(cs
, 1, HDLC_STATUS
);
635 debugl1(cs
, "HDLC 2 STA %x", val
);
636 val
= ReadHDLCPnP(cs
, 1, HDLC_STATUS
+ 1);
637 debugl1(cs
, "HDLC 2 RML %x", val
);
638 val
= ReadHDLCPnP(cs
, 1, HDLC_STATUS
+ 2);
639 debugl1(cs
, "HDLC 2 MODE %x", val
);
640 val
= ReadHDLCPnP(cs
, 1, HDLC_STATUS
+ 3);
641 debugl1(cs
, "HDLC 2 VIN %x", val
);
646 inithdlc(struct IsdnCardState
*cs
)
648 cs
->bcs
[0].BC_SetStack
= setstack_hdlc
;
649 cs
->bcs
[1].BC_SetStack
= setstack_hdlc
;
650 cs
->bcs
[0].BC_Close
= close_hdlcstate
;
651 cs
->bcs
[1].BC_Close
= close_hdlcstate
;
652 modehdlc(cs
->bcs
, -1, 0);
653 modehdlc(cs
->bcs
+ 1, -1, 1);
657 avm_pcipnp_interrupt(int intno
, void *dev_id
, struct pt_regs
*regs
)
659 struct IsdnCardState
*cs
= dev_id
;
664 spin_lock_irqsave(&cs
->lock
, flags
);
665 sval
= inb(cs
->hw
.avm
.cfg_reg
+ 2);
666 if ((sval
& AVM_STATUS0_IRQ_MASK
) == AVM_STATUS0_IRQ_MASK
) {
667 /* possible a shared IRQ reqest */
668 spin_unlock_irqrestore(&cs
->lock
, flags
);
671 if (!(sval
& AVM_STATUS0_IRQ_ISAC
)) {
672 val
= ReadISAC(cs
, ISAC_ISTA
);
673 isac_interrupt(cs
, val
);
675 if (!(sval
& AVM_STATUS0_IRQ_HDLC
)) {
678 WriteISAC(cs
, ISAC_MASK
, 0xFF);
679 WriteISAC(cs
, ISAC_MASK
, 0x0);
680 spin_unlock_irqrestore(&cs
->lock
, flags
);
685 reset_avmpcipnp(struct IsdnCardState
*cs
)
687 printk(KERN_INFO
"AVM PCI/PnP: reset\n");
688 outb(AVM_STATUS0_RESET
| AVM_STATUS0_DIS_TIMER
, cs
->hw
.avm
.cfg_reg
+ 2);
690 outb(AVM_STATUS0_DIS_TIMER
| AVM_STATUS0_RES_TIMER
| AVM_STATUS0_ENA_IRQ
, cs
->hw
.avm
.cfg_reg
+ 2);
691 outb(AVM_STATUS1_ENA_IOM
| cs
->irq
, cs
->hw
.avm
.cfg_reg
+ 3);
693 printk(KERN_INFO
"AVM PCI/PnP: S1 %x\n", inb(cs
->hw
.avm
.cfg_reg
+ 3));
697 AVM_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
703 spin_lock_irqsave(&cs
->lock
, flags
);
705 spin_unlock_irqrestore(&cs
->lock
, flags
);
708 outb(0, cs
->hw
.avm
.cfg_reg
+ 2);
709 release_region(cs
->hw
.avm
.cfg_reg
, 32);
712 spin_lock_irqsave(&cs
->lock
, flags
);
714 clear_pending_isac_ints(cs
);
717 outb(AVM_STATUS0_DIS_TIMER
| AVM_STATUS0_RES_TIMER
,
718 cs
->hw
.avm
.cfg_reg
+ 2);
719 WriteISAC(cs
, ISAC_MASK
, 0);
720 outb(AVM_STATUS0_DIS_TIMER
| AVM_STATUS0_RES_TIMER
|
721 AVM_STATUS0_ENA_IRQ
, cs
->hw
.avm
.cfg_reg
+ 2);
722 /* RESET Receiver and Transmitter */
723 WriteISAC(cs
, ISAC_CMDR
, 0x41);
724 spin_unlock_irqrestore(&cs
->lock
, flags
);
733 static struct pci_dev
*dev_avm __initdata
= NULL
;
736 static struct pnp_card
*pnp_avm_c __initdata
= NULL
;
740 setup_avm_pcipnp(struct IsdnCard
*card
)
743 struct IsdnCardState
*cs
= card
->cs
;
746 strcpy(tmp
, avm_pci_rev
);
747 printk(KERN_INFO
"HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp
));
748 if (cs
->typ
!= ISDN_CTYPE_FRITZPCI
)
751 /* old manual method */
752 cs
->hw
.avm
.cfg_reg
= card
->para
[1];
753 cs
->irq
= card
->para
[0];
754 cs
->subtyp
= AVM_FRITZ_PNP
;
758 if (isapnp_present()) {
759 struct pnp_dev
*pnp_avm_d
= NULL
;
760 if ((pnp_avm_c
= pnp_find_card(
761 ISAPNP_VENDOR('A', 'V', 'M'),
762 ISAPNP_FUNCTION(0x0900), pnp_avm_c
))) {
763 if ((pnp_avm_d
= pnp_find_dev(pnp_avm_c
,
764 ISAPNP_VENDOR('A', 'V', 'M'),
765 ISAPNP_FUNCTION(0x0900), pnp_avm_d
))) {
768 pnp_disable_dev(pnp_avm_d
);
769 err
= pnp_activate_dev(pnp_avm_d
);
771 printk(KERN_WARNING
"%s: pnp_activate_dev ret(%d)\n",
776 pnp_port_start(pnp_avm_d
, 0);
777 cs
->irq
= pnp_irq(pnp_avm_d
, 0);
779 printk(KERN_ERR
"FritzPnP:No IRQ\n");
782 if (!cs
->hw
.avm
.cfg_reg
) {
783 printk(KERN_ERR
"FritzPnP:No IO address\n");
786 cs
->subtyp
= AVM_FRITZ_PNP
;
791 printk(KERN_INFO
"FritzPnP: no ISA PnP present\n");
795 if ((dev_avm
= pci_find_device(PCI_VENDOR_ID_AVM
,
796 PCI_DEVICE_ID_AVM_A1
, dev_avm
))) {
797 if (pci_enable_device(dev_avm
))
799 cs
->irq
= dev_avm
->irq
;
801 printk(KERN_ERR
"FritzPCI: No IRQ for PCI card found\n");
804 cs
->hw
.avm
.cfg_reg
= pci_resource_start(dev_avm
, 1);
805 if (!cs
->hw
.avm
.cfg_reg
) {
806 printk(KERN_ERR
"FritzPCI: No IO-Adr for PCI card found\n");
809 cs
->subtyp
= AVM_FRITZ_PCI
;
811 printk(KERN_WARNING
"FritzPCI: No PCI card found\n");
814 cs
->irq_flags
|= SA_SHIRQ
;
816 printk(KERN_WARNING
"FritzPCI: NO_PCI_BIOS\n");
818 #endif /* CONFIG_PCI */
820 cs
->hw
.avm
.isac
= cs
->hw
.avm
.cfg_reg
+ 0x10;
821 if (!request_region(cs
->hw
.avm
.cfg_reg
, 32,
822 (cs
->subtyp
== AVM_FRITZ_PCI
) ? "avm PCI" : "avm PnP")) {
824 "HiSax: %s config port %x-%x already in use\n",
827 cs
->hw
.avm
.cfg_reg
+ 31);
830 switch (cs
->subtyp
) {
832 val
= inl(cs
->hw
.avm
.cfg_reg
);
833 printk(KERN_INFO
"AVM PCI: stat %#x\n", val
);
834 printk(KERN_INFO
"AVM PCI: Class %X Rev %d\n",
835 val
& 0xff, (val
>>8) & 0xff);
836 cs
->BC_Read_Reg
= &ReadHDLC_s
;
837 cs
->BC_Write_Reg
= &WriteHDLC_s
;
840 val
= inb(cs
->hw
.avm
.cfg_reg
);
841 ver
= inb(cs
->hw
.avm
.cfg_reg
+ 1);
842 printk(KERN_INFO
"AVM PnP: Class %X Rev %d\n", val
, ver
);
843 cs
->BC_Read_Reg
= &ReadHDLCPnP
;
844 cs
->BC_Write_Reg
= &WriteHDLCPnP
;
847 printk(KERN_WARNING
"AVM unknown subtype %d\n", cs
->subtyp
);
850 printk(KERN_INFO
"HiSax: %s config irq:%d base:0x%X\n",
851 (cs
->subtyp
== AVM_FRITZ_PCI
) ? "AVM Fritz!PCI" : "AVM Fritz!PnP",
852 cs
->irq
, cs
->hw
.avm
.cfg_reg
);
855 cs
->readisac
= &ReadISAC
;
856 cs
->writeisac
= &WriteISAC
;
857 cs
->readisacfifo
= &ReadISACfifo
;
858 cs
->writeisacfifo
= &WriteISACfifo
;
859 cs
->BC_Send_Data
= &hdlc_fill_fifo
;
860 cs
->cardmsg
= &AVM_card_msg
;
861 cs
->irq_func
= &avm_pcipnp_interrupt
;
862 cs
->writeisac(cs
, ISAC_MASK
, 0xFF);
863 ISACVersion(cs
, (cs
->subtyp
== AVM_FRITZ_PCI
) ? "AVM PCI:" : "AVM PnP:");