1 /* $Id: foreign.c,v 1.1 1998/11/09 07:48:48 baccala Exp $
3 * HiSax ISDN driver - foreign chipset interface
5 * Author Brent Baccala (baccala@FreeSoft.org)
10 * Revision 1.1 1998/11/09 07:48:48 baccala
11 * Initial DBRI ISDN code. Sometimes works (brings up the link and you
12 * can telnet through it), sometimes doesn't (crashes the machine)
14 * Revision 1.2 1998/02/12 23:07:10 keil
15 * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
17 * Revision 1.1 1998/02/03 23:20:51 keil
18 * New files for SPARC isdn support
20 * Revision 1.1 1998/01/08 04:17:12 baccala
21 * ISDN comes to the Sparc. Key points:
23 * - Existing ISDN HiSax driver provides all the smarts
24 * - it compiles, runs, talks to an isolated phone switch, connects
25 * to a Cisco, pings go through
26 * - AMD 7930 support only (no DBRI yet)
27 * - no US NI-1 support (may not work on US phone system - untested)
28 * - periodic packet loss, apparently due to lost interrupts
29 * - ISDN sometimes freezes, requiring reboot before it will work again
31 * The code is unreliable enough to be consider alpha
37 #define __NO_VERSION__
43 #include <linux/interrupt.h>
45 static const char *foreign_revision
= "$Revision: 1.1 $";
47 #define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */
48 #define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into
49 * (must divide RCV_BUFSIZE) */
51 static void Bchan_fill_fifo(struct BCState
*, struct sk_buff
*);
54 Bchan_xmt_bh(struct BCState
*bcs
)
58 if (bcs
->hw
.foreign
.tx_skb
!= NULL
) {
59 dev_kfree_skb(bcs
->hw
.foreign
.tx_skb
);
60 bcs
->hw
.foreign
.tx_skb
= NULL
;
63 if ((skb
= skb_dequeue(&bcs
->squeue
))) {
64 Bchan_fill_fifo(bcs
, skb
);
66 clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
67 bcs
->event
|= 1 << B_XMTBUFREADY
;
68 queue_task(&bcs
->tqueue
, &tq_immediate
);
69 mark_bh(IMMEDIATE_BH
);
74 Bchan_xmit_callback(struct BCState
*bcs
)
76 queue_task(&bcs
->hw
.foreign
.tq_xmt
, &tq_immediate
);
77 mark_bh(IMMEDIATE_BH
);
80 /* B channel transmission: two modes (three, if you count L1_MODE_NULL)
82 * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
83 * the packet (i.e. make_raw_hdlc_data). Since this can be a
84 * time-consuming operation, our completion callback just schedules
85 * a bottom half to do encapsulation for the next packet. In between,
86 * the link will just idle
88 * L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap,
89 * and we can't just let the link idle, so the "bottom half" actually
90 * gets called during the top half (it's our callback routine in this case),
91 * but it's a lot faster now since we don't call make_raw_hdlc_data
95 Bchan_fill_fifo(struct BCState
*bcs
, struct sk_buff
*skb
)
97 struct IsdnCardState
*cs
= bcs
->cs
;
98 struct foreign_hw
*hw
= &bcs
->hw
.foreign
;
101 if ((cs
->debug
& L1_DEB_HSCX
) || (cs
->debug
& L1_DEB_HSCX_FIFO
)) {
105 t
+= sprintf(t
, "Bchan_fill_fifo %c cnt %d",
106 bcs
->channel
? 'B' : 'A', skb
->len
);
107 if (cs
->debug
& L1_DEB_HSCX_FIFO
)
108 QuickHex(t
, skb
->data
, skb
->len
);
112 if (hw
->doHDLCprocessing
) {
113 len
= make_raw_hdlc_data(skb
->data
, skb
->len
,
114 bcs
->hw
.foreign
.tx_buff
, RAW_BUFMAX
);
116 cs
->hw
.foreign
->bxmit(0, bcs
->channel
,
117 bcs
->hw
.foreign
.tx_buff
, len
,
118 (void *) &Bchan_xmit_callback
,
122 cs
->hw
.foreign
->bxmit(0, bcs
->channel
,
124 (void *) &Bchan_xmit_callback
,
126 bcs
->hw
.foreign
.tx_skb
= skb
;
131 Bchan_mode(struct BCState
*bcs
, int mode
, int bc
)
133 struct IsdnCardState
*cs
= bcs
->cs
;
135 if (cs
->debug
& L1_DEB_HSCX
) {
137 sprintf(tmp
, "foreign mode %d bchan %d/%d",
138 mode
, bc
, bcs
->channel
);
144 /* Bchan_l2l1 is the entry point for upper layer routines that want to
145 * transmit on the B channel. PH_DATA_REQ is a normal packet that
146 * we either start transmitting (if idle) or queue (if busy).
147 * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
148 * once the link is idle. After a "pull" callback, the upper layer
149 * routines can use PH_PULL_IND to send data.
153 Bchan_l2l1(struct PStack
*st
, int pr
, void *arg
)
155 struct sk_buff
*skb
= arg
;
159 if (test_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
)) {
160 skb_queue_tail(&st
->l1
.bcs
->squeue
, skb
);
162 test_and_set_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
);
163 Bchan_fill_fifo(st
->l1
.bcs
, skb
);
167 if (test_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
)) {
168 printk(KERN_WARNING
"foreign: this shouldn't happen\n");
171 test_and_set_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
);
172 Bchan_fill_fifo(st
->l1
.bcs
, skb
);
175 if (!test_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
)) {
176 clear_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
177 st
->l1
.l1l2(st
, PH_PULL_CNF
, NULL
);
179 set_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
185 ****************************************************************************
186 ***************** Receiver callback and bottom half ************************
187 ****************************************************************************
190 /* Bchan_recv_done() is called when a frame has been completely decoded
191 * into hw->rv_skb and we're ready to hand it off to the HiSax upper
192 * layer. If a "large" packet is received, stick rv_skb on the
193 * receive queue and alloc a new (large) skb to act as buffer for
194 * future receives. If a small packet is received, leave rv_skb
195 * alone, alloc a new skb of the correct size, and copy the packet
196 * into it. In any case, flag the channel as B_RCVBUFREADY and
197 * queue the upper layer's task.
201 Bchan_recv_done(struct BCState
*bcs
, unsigned int len
)
203 struct IsdnCardState
*cs
= bcs
->cs
;
204 struct foreign_hw
*hw
= &bcs
->hw
.foreign
;
207 if (cs
->debug
& L1_DEB_HSCX_FIFO
) {
211 t
+= sprintf(t
, "Bchan_rcv %c cnt %d (%x)", bcs
->channel
? 'B' : 'A', len
, hw
->rv_skb
->tail
);
212 QuickHex(t
, hw
->rv_skb
->tail
, len
);
216 if (len
> HSCX_BUFMAX
/2) {
217 /* Large packet received */
219 if (!(skb
= dev_alloc_skb(HSCX_BUFMAX
))) {
220 printk(KERN_WARNING
"foreign: receive out of memory\n");
222 skb_put(hw
->rv_skb
, len
);
223 skb_queue_tail(&bcs
->rqueue
, hw
->rv_skb
);
226 bcs
->event
|= 1 << B_RCVBUFREADY
;
227 queue_task(&bcs
->tqueue
, &tq_immediate
);
228 mark_bh(IMMEDIATE_BH
);
231 /* Small packet received */
233 if (!(skb
= dev_alloc_skb(len
))) {
234 printk(KERN_WARNING
"foreign: receive out of memory\n");
236 memcpy(skb_put(skb
, len
), hw
->rv_skb
->tail
, len
);
237 skb_queue_tail(&bcs
->rqueue
, skb
);
239 bcs
->event
|= 1 << B_RCVBUFREADY
;
240 queue_task(&bcs
->tqueue
, &tq_immediate
);
241 mark_bh(IMMEDIATE_BH
);
246 /* Bchan_recv_callback()'s behavior depends on whether we're doing local
247 * HDLC processing. If so, receive into hw->rv_buff and queue Bchan_rcv_bh
248 * to decode the HDLC at leisure. Otherwise, receive directly into hw->rv_skb
249 * and call Bchan_recv_done(). In either case, prepare a new buffer for
250 * further receives and hand it to the hardware driver.
254 Bchan_recv_callback(struct BCState
*bcs
, int error
, unsigned int len
)
256 struct IsdnCardState
*cs
= bcs
->cs
;
257 struct foreign_hw
*hw
= &bcs
->hw
.foreign
;
259 if (hw
->doHDLCprocessing
) {
261 hw
->rv_buff_in
+= RCV_BUFSIZE
/RCV_BUFBLKS
;
262 hw
->rv_buff_in
%= RCV_BUFSIZE
;
264 if (hw
->rv_buff_in
!= hw
->rv_buff_out
) {
265 cs
->hw
.foreign
->brecv(0, bcs
->channel
,
266 hw
->rv_buff
+ hw
->rv_buff_in
,
267 RCV_BUFSIZE
/RCV_BUFBLKS
,
268 (void *) &Bchan_recv_callback
,
272 queue_task(&hw
->tq_rcv
, &tq_immediate
);
273 mark_bh(IMMEDIATE_BH
);
278 sprintf(tmp
, "B channel %c receive error %x",
279 bcs
->channel
? 'B' : 'A', error
);
282 Bchan_recv_done(bcs
, len
);
284 cs
->hw
.foreign
->brecv(0, bcs
->channel
,
285 hw
->rv_skb
->tail
, HSCX_BUFMAX
,
286 (void *) &Bchan_recv_callback
,
292 /* Bchan_rcv_bh() is a "shim" bottom half handler stuck in between
293 * Bchan_recv_callback() and the HiSax upper layer if we need to
294 * do local HDLC processing.
298 Bchan_rcv_bh(struct BCState
*bcs
)
300 struct IsdnCardState
*cs
= bcs
->cs
;
301 struct foreign_hw
*hw
= &bcs
->hw
.foreign
;
305 if (cs
->debug
& L1_DEB_HSCX
) {
308 sprintf(tmp
, "foreign_Bchan_rcv (%d/%d)",
309 hw
->rv_buff_in
, hw
->rv_buff_out
);
314 if (cs
->debug
& L1_DEB_HSCX
) {
317 QuickHex(tmp
, hw
->rv_buff
+ hw
->rv_buff_out
,
318 RCV_BUFSIZE
/RCV_BUFBLKS
);
322 while ((len
= read_raw_hdlc_data(hw
->hdlc_state
,
323 hw
->rv_buff
+ hw
->rv_buff_out
, RCV_BUFSIZE
/RCV_BUFBLKS
,
324 hw
->rv_skb
->tail
, HSCX_BUFMAX
))) {
326 Bchan_recv_done(bcs
, len
);
329 sprintf(tmp
, "B channel %c receive error",
330 bcs
->channel
? 'B' : 'A');
335 if (hw
->rv_buff_in
== hw
->rv_buff_out
) {
336 /* Buffer was filled up - need to restart receiver */
337 cs
->hw
.foreign
->brecv(0, bcs
->channel
,
338 hw
->rv_buff
+ hw
->rv_buff_in
,
339 RCV_BUFSIZE
/RCV_BUFBLKS
,
340 (void *) &Bchan_recv_callback
,
344 hw
->rv_buff_out
+= RCV_BUFSIZE
/RCV_BUFBLKS
;
345 hw
->rv_buff_out
%= RCV_BUFSIZE
;
347 } while (hw
->rv_buff_in
!= hw
->rv_buff_out
);
351 Bchan_close(struct BCState
*bcs
)
353 struct IsdnCardState
*cs
= bcs
->cs
;
356 Bchan_mode(bcs
, 0, 0);
357 cs
->hw
.foreign
->bclose(0, bcs
->channel
);
359 if (test_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
360 while ((skb
= skb_dequeue(&bcs
->rqueue
))) {
363 while ((skb
= skb_dequeue(&bcs
->squeue
))) {
367 test_and_clear_bit(BC_FLG_INIT
, &bcs
->Flag
);
371 Bchan_open(struct BCState
*bcs
)
373 struct IsdnCardState
*cs
= bcs
->cs
;
374 struct foreign_hw
*hw
= &bcs
->hw
.foreign
;
376 if (!test_and_set_bit(BC_FLG_INIT
, &bcs
->Flag
)) {
377 skb_queue_head_init(&bcs
->rqueue
);
378 skb_queue_head_init(&bcs
->squeue
);
380 test_and_clear_bit(BC_FLG_BUSY
, &bcs
->Flag
);
382 hw
->doHDLCprocessing
= 0;
383 if (bcs
->mode
== L1_MODE_HDLC
) {
384 if (cs
->hw
.foreign
->bopen(0, bcs
->channel
, 1, 0xff) == -1) {
385 if (cs
->hw
.foreign
->bopen(0, bcs
->channel
, 0, 0xff) == -1) {
388 hw
->doHDLCprocessing
= 1;
391 if (cs
->hw
.foreign
->bopen(0, bcs
->channel
, 0, 0xff) == -1) {
399 init_hdlc_state(hw
->hdlc_state
, 0);
400 cs
->hw
.foreign
->brecv(0, bcs
->channel
,
401 hw
->rv_buff
+ hw
->rv_buff_in
,
402 RCV_BUFSIZE
/RCV_BUFBLKS
,
403 (void *) &Bchan_recv_callback
, (void *) bcs
);
411 Bchan_init(struct BCState
*bcs
)
413 if (!(bcs
->hw
.foreign
.tx_buff
= kmalloc(RAW_BUFMAX
, GFP_ATOMIC
))) {
415 "HiSax: No memory for foreign.tx_buff\n");
418 if (!(bcs
->hw
.foreign
.rv_buff
= kmalloc(RCV_BUFSIZE
, GFP_ATOMIC
))) {
420 "HiSax: No memory for foreign.rv_buff\n");
423 if (!(bcs
->hw
.foreign
.rv_skb
= dev_alloc_skb(HSCX_BUFMAX
))) {
425 "HiSax: No memory for foreign.rv_skb\n");
428 if (!(bcs
->hw
.foreign
.hdlc_state
= kmalloc(sizeof(struct hdlc_state
),
431 "HiSax: No memory for foreign.hdlc_state\n");
435 bcs
->hw
.foreign
.tq_rcv
.sync
= 0;
436 bcs
->hw
.foreign
.tq_rcv
.routine
= (void (*)(void *)) &Bchan_rcv_bh
;
437 bcs
->hw
.foreign
.tq_rcv
.data
= (void *) bcs
;
439 bcs
->hw
.foreign
.tq_xmt
.sync
= 0;
440 bcs
->hw
.foreign
.tq_xmt
.routine
= (void (*)(void *)) &Bchan_xmt_bh
;
441 bcs
->hw
.foreign
.tq_xmt
.data
= (void *) bcs
;
445 Bchan_manl1(struct PStack
*st
, int pr
,
449 case (PH_ACTIVATE_REQ
):
450 test_and_set_bit(BC_FLG_ACTIV
, &st
->l1
.bcs
->Flag
);
451 Bchan_mode(st
->l1
.bcs
, st
->l1
.mode
, st
->l1
.bc
);
452 st
->l1
.l1man(st
, PH_ACTIVATE_CNF
, NULL
);
454 case (PH_DEACTIVATE_REQ
):
455 if (!test_bit(BC_FLG_BUSY
, &st
->l1
.bcs
->Flag
))
456 Bchan_mode(st
->l1
.bcs
, 0, 0);
457 test_and_clear_bit(BC_FLG_ACTIV
, &st
->l1
.bcs
->Flag
);
463 setstack_foreign(struct PStack
*st
, struct BCState
*bcs
)
468 st
->l2
.l2l1
= Bchan_l2l1
;
469 st
->ma
.manl1
= Bchan_manl1
;
470 setstack_manager(st
);
477 foreign_drecv_callback(void *arg
, int error
, unsigned int count
)
479 struct IsdnCardState
*cs
= (struct IsdnCardState
*) arg
;
480 static struct tq_struct task
= {0, 0, (void *) &DChannel_proc_rcv
, 0};
483 /* NOTE: This function is called directly from an interrupt handler */
486 if (!(skb
= alloc_skb(count
, GFP_ATOMIC
)))
487 printk(KERN_WARNING
"HiSax: D receive out of memory\n");
489 memcpy(skb_put(skb
, count
), cs
->rcvbuf
, count
);
490 skb_queue_tail(&cs
->rq
, skb
);
493 task
.data
= (void *) cs
;
494 queue_task(&task
, &tq_immediate
);
495 mark_bh(IMMEDIATE_BH
);
498 if (cs
->debug
& L1_DEB_ISAC_FIFO
) {
502 t
+= sprintf(t
, "foreign Drecv cnt %d", count
);
503 if (error
) t
+= sprintf(t
, " ERR %x", error
);
504 QuickHex(t
, cs
->rcvbuf
, count
);
508 cs
->hw
.foreign
->drecv(0, cs
->rcvbuf
, MAX_DFRAME_LEN
,
509 &foreign_drecv_callback
, cs
);
513 foreign_dxmit_callback(void *arg
, int error
)
515 struct IsdnCardState
*cs
= (struct IsdnCardState
*) arg
;
516 static struct tq_struct task
= {0, 0, (void *) &DChannel_proc_xmt
, 0};
518 /* NOTE: This function is called directly from an interrupt handler */
520 /* may wish to do retransmission here, if error indicates collision */
522 if (cs
->debug
& L1_DEB_ISAC_FIFO
) {
526 t
+= sprintf(t
, "foreign Dxmit cnt %d", cs
->tx_skb
->len
);
527 if (error
) t
+= sprintf(t
, " ERR %x", error
);
528 QuickHex(t
, cs
->tx_skb
->data
, cs
->tx_skb
->len
);
534 task
.data
= (void *) cs
;
535 queue_task(&task
, &tq_immediate
);
536 mark_bh(IMMEDIATE_BH
);
540 foreign_Dchan_l2l1(struct PStack
*st
, int pr
, void *arg
)
542 struct IsdnCardState
*cs
= (struct IsdnCardState
*) st
->l1
.hardware
;
543 struct sk_buff
*skb
= arg
;
549 skb_queue_tail(&cs
->sq
, skb
);
550 #ifdef L2FRAME_DEBUG /* psa */
551 if (cs
->debug
& L1_DEB_LAPD
)
552 Logl2Frame(cs
, skb
, "PH_DATA Queued", 0);
555 if ((cs
->dlogflag
) && (!(skb
->data
[2] & 1))) {
557 LogFrame(cs
, skb
->data
, skb
->len
);
558 sprintf(str
, "Q.931 frame user->network tei %d", st
->l2
.tei
);
559 dlogframe(cs
, skb
->data
+4, skb
->len
-4,
564 #ifdef L2FRAME_DEBUG /* psa */
565 if (cs
->debug
& L1_DEB_LAPD
)
566 Logl2Frame(cs
, skb
, "PH_DATA", 0);
568 cs
->hw
.foreign
->dxmit(0, skb
->data
, skb
->len
,
569 &foreign_dxmit_callback
, cs
);
574 if (cs
->debug
& L1_DEB_WARN
)
575 debugl1(cs
, " l2l1 tx_skb exist this shouldn't happen");
576 skb_queue_tail(&cs
->sq
, skb
);
579 if ((cs
->dlogflag
) && (!(skb
->data
[2] & 1))) { /* I-FRAME */
580 LogFrame(cs
, skb
->data
, skb
->len
);
581 sprintf(str
, "Q.931 frame user->network tei %d", st
->l2
.tei
);
582 dlogframe(cs
, skb
->data
+ 4, skb
->len
- 4,
587 #ifdef L2FRAME_DEBUG /* psa */
588 if (cs
->debug
& L1_DEB_LAPD
)
589 Logl2Frame(cs
, skb
, "PH_DATA_PULLED", 0);
591 cs
->hw
.foreign
->dxmit(0, cs
->tx_skb
->data
, cs
->tx_skb
->len
,
592 &foreign_dxmit_callback
, cs
);
595 #ifdef L2FRAME_DEBUG /* psa */
596 if (cs
->debug
& L1_DEB_LAPD
)
597 debugl1(cs
, "-> PH_REQUEST_PULL");
600 test_and_clear_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
601 st
->l1
.l1l2(st
, PH_PULL_CNF
, NULL
);
603 test_and_set_bit(FLG_L1_PULL_REQ
, &st
->l1
.Flags
);
609 setDstack_foreign(struct PStack
*st
, struct IsdnCardState
*cs
)
611 st
->l2
.l2l1
= foreign_Dchan_l2l1
;
613 printk("setDstack_foreign: No cs->rcvbuf!\n");
615 cs
->hw
.foreign
->drecv(0, cs
->rcvbuf
, MAX_DFRAME_LEN
,
616 &foreign_drecv_callback
, cs
);
622 manl1_msg(struct IsdnCardState
*cs
, int msg
, void *arg
) {
627 st
->ma
.manl1(st
, msg
, arg
);
633 foreign_l1cmd(struct IsdnCardState
*cs
, int msg
, void *arg
)
638 if (cs
->debug
& L1_DEB_ISAC
) {
639 sprintf(tmp
, "foreign_l1cmd msg %x", msg
);
645 cs
->hw
.foreign
->liu_deactivate(0);
646 manl1_msg(cs
, PH_POWERUP_CNF
, NULL
);
651 cs
->hw
.foreign
->liu_activate(0,0);
653 case PH_TESTLOOP_REQ
:
656 if (cs
->debug
& L1_DEB_WARN
) {
657 sprintf(tmp
, "foreign_l1cmd unknown %4x", msg
);
665 foreign_new_ph(struct IsdnCardState
*cs
)
667 switch (cs
->hw
.foreign
->get_liu_state(0)) {
669 manl1_msg(cs
, PH_POWERUP_CNF
, NULL
);
673 manl1_msg(cs
, PH_I4_P8_IND
, NULL
);
677 manl1_msg(cs
, PH_RSYNC_IND
, NULL
);
682 /* LIU state change callback */
685 foreign_liu_callback(struct IsdnCardState
*cs
)
687 static struct tq_struct task
= {0, 0, (void *) &foreign_new_ph
, 0};
692 if (cs
->debug
& L1_DEB_ISAC
) {
694 sprintf(tmp
, "foreign LIU state %d",
695 cs
->hw
.foreign
->get_liu_state(0));
699 task
.data
= (void *) cs
;
700 queue_task(&task
, &tq_immediate
);
701 mark_bh(IMMEDIATE_BH
);
704 static void init_foreign(struct IsdnCardState
*cs
)
706 Bchan_init(&cs
->bcs
[0]);
707 Bchan_init(&cs
->bcs
[1]);
708 cs
->bcs
[0].BC_SetStack
= setstack_foreign
;
709 cs
->bcs
[1].BC_SetStack
= setstack_foreign
;
710 cs
->bcs
[0].BC_Close
= Bchan_close
;
711 cs
->bcs
[1].BC_Close
= Bchan_close
;
712 Bchan_mode(cs
->bcs
, 0, 0);
713 Bchan_mode(cs
->bcs
+ 1, 0, 0);
717 foreign_card_msg(struct IsdnCardState
*cs
, int mt
, void *arg
)
727 cs
->l1cmd
= foreign_l1cmd
;
728 cs
->setstack_d
= setDstack_foreign
;
729 cs
->hw
.foreign
->liu_init(0, &foreign_liu_callback
,
740 extern struct foreign_interface amd7930_foreign_interface
;
744 extern struct foreign_interface dbri_foreign_interface
;
748 setup_foreign(struct IsdnCard
*card
)
750 struct IsdnCardState
*cs
= card
->cs
;
753 strcpy(tmp
, foreign_revision
);
754 printk(KERN_INFO
"HiSax: Foreign chip driver Rev. %s\n",
758 if (cs
->typ
== ISDN_CTYPE_AMD7930
) {
759 cs
->hw
.foreign
= &amd7930_foreign_interface
;
760 cs
->irq
= cs
->hw
.foreign
->get_irqnum(0);
763 cs
->cardmsg
= &foreign_card_msg
;
769 if (cs
->typ
== ISDN_CTYPE_DBRI
) {
770 cs
->hw
.foreign
= &dbri_foreign_interface
;
771 cs
->irq
= cs
->hw
.foreign
->get_irqnum(0);
774 cs
->cardmsg
= &foreign_card_msg
;