Import 2.3.10pre5
[davej-history.git] / drivers / isdn / hisax / foreign.c
blobb8ffa4948682dfd518903bb8570b3f1c0a9680fc
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)
9 * $Log: foreign.c,v $
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__
38 #include "hisax.h"
39 #include "isac.h"
40 #include "isdnl1.h"
41 #include "foreign.h"
42 #include "rawhdlc.h"
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 *);
53 static void
54 Bchan_xmt_bh(struct BCState *bcs)
56 struct sk_buff *skb;
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);
65 } else {
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);
73 static void
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
94 static void
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;
99 int len;
101 if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
102 char tmp[2048];
103 char *t = tmp;
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);
109 debugl1(cs, tmp);
112 if (hw->doHDLCprocessing) {
113 len = make_raw_hdlc_data(skb->data, skb->len,
114 bcs->hw.foreign.tx_buff, RAW_BUFMAX);
115 if (len > 0)
116 cs->hw.foreign->bxmit(0, bcs->channel,
117 bcs->hw.foreign.tx_buff, len,
118 (void *) &Bchan_xmit_callback,
119 (void *) bcs);
120 dev_kfree_skb(skb);
121 } else {
122 cs->hw.foreign->bxmit(0, bcs->channel,
123 skb->data, skb->len,
124 (void *) &Bchan_xmit_callback,
125 (void *) bcs);
126 bcs->hw.foreign.tx_skb = skb;
130 static void
131 Bchan_mode(struct BCState *bcs, int mode, int bc)
133 struct IsdnCardState *cs = bcs->cs;
135 if (cs->debug & L1_DEB_HSCX) {
136 char tmp[40];
137 sprintf(tmp, "foreign mode %d bchan %d/%d",
138 mode, bc, bcs->channel);
139 debugl1(cs, tmp);
141 bcs->mode = mode;
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.
152 static void
153 Bchan_l2l1(struct PStack *st, int pr, void *arg)
155 struct sk_buff *skb = arg;
157 switch (pr) {
158 case (PH_DATA_REQ):
159 if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
160 skb_queue_tail(&st->l1.bcs->squeue, skb);
161 } else {
162 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
163 Bchan_fill_fifo(st->l1.bcs, skb);
165 break;
166 case (PH_PULL_IND):
167 if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
168 printk(KERN_WARNING "foreign: this shouldn't happen\n");
169 break;
171 test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
172 Bchan_fill_fifo(st->l1.bcs, skb);
173 break;
174 case (PH_PULL_REQ):
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);
178 } else
179 set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
180 break;
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.
200 static void
201 Bchan_recv_done(struct BCState *bcs, unsigned int len)
203 struct IsdnCardState *cs = bcs->cs;
204 struct foreign_hw *hw = &bcs->hw.foreign;
205 struct sk_buff *skb;
207 if (cs->debug & L1_DEB_HSCX_FIFO) {
208 char tmp[2048];
209 char *t = tmp;
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);
213 debugl1(cs, tmp);
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");
221 } else {
222 skb_put(hw->rv_skb, len);
223 skb_queue_tail(&bcs->rqueue, hw->rv_skb);
224 hw->rv_skb = skb;
226 bcs->event |= 1 << B_RCVBUFREADY;
227 queue_task(&bcs->tqueue, &tq_immediate);
228 mark_bh(IMMEDIATE_BH);
230 } else {
231 /* Small packet received */
233 if (!(skb = dev_alloc_skb(len))) {
234 printk(KERN_WARNING "foreign: receive out of memory\n");
235 } else {
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.
253 static void
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,
269 (void *) bcs);
272 queue_task(&hw->tq_rcv, &tq_immediate);
273 mark_bh(IMMEDIATE_BH);
275 } else {
276 if (error) {
277 char tmp[256];
278 sprintf(tmp, "B channel %c receive error %x",
279 bcs->channel ? 'B' : 'A', error);
280 debugl1(cs, tmp);
281 } else {
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,
287 (void *) bcs);
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.
297 static void
298 Bchan_rcv_bh(struct BCState *bcs)
300 struct IsdnCardState *cs = bcs->cs;
301 struct foreign_hw *hw = &bcs->hw.foreign;
302 struct sk_buff *skb;
303 int len;
305 if (cs->debug & L1_DEB_HSCX) {
306 char tmp[1024];
308 sprintf(tmp, "foreign_Bchan_rcv (%d/%d)",
309 hw->rv_buff_in, hw->rv_buff_out);
310 debugl1(cs, tmp);
313 do {
314 if (cs->debug & L1_DEB_HSCX) {
315 char tmp[1024];
317 QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
318 RCV_BUFSIZE/RCV_BUFBLKS);
319 debugl1(cs, tmp);
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))) {
325 if (len > 0) {
326 Bchan_recv_done(bcs, len);
327 } else {
328 char tmp[256];
329 sprintf(tmp, "B channel %c receive error",
330 bcs->channel ? 'B' : 'A');
331 debugl1(cs, tmp);
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,
341 (void *) bcs);
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);
350 static void
351 Bchan_close(struct BCState *bcs)
353 struct IsdnCardState *cs = bcs->cs;
354 struct sk_buff *skb;
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))) {
361 dev_kfree_skb(skb);
363 while ((skb = skb_dequeue(&bcs->squeue))) {
364 dev_kfree_skb(skb);
367 test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
370 static int
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) {
386 return (-1);
388 hw->doHDLCprocessing = 1;
390 } else {
391 if (cs->hw.foreign->bopen(0, bcs->channel, 0, 0xff) == -1) {
392 return (-1);
396 hw->rv_buff_in = 0;
397 hw->rv_buff_out = 0;
398 hw->tx_skb = NULL;
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);
405 bcs->event = 0;
406 bcs->tx_cnt = 0;
407 return (0);
410 static void
411 Bchan_init(struct BCState *bcs)
413 if (!(bcs->hw.foreign.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
414 printk(KERN_WARNING
415 "HiSax: No memory for foreign.tx_buff\n");
416 return;
418 if (!(bcs->hw.foreign.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
419 printk(KERN_WARNING
420 "HiSax: No memory for foreign.rv_buff\n");
421 return;
423 if (!(bcs->hw.foreign.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
424 printk(KERN_WARNING
425 "HiSax: No memory for foreign.rv_skb\n");
426 return;
428 if (!(bcs->hw.foreign.hdlc_state = kmalloc(sizeof(struct hdlc_state),
429 GFP_ATOMIC))) {
430 printk(KERN_WARNING
431 "HiSax: No memory for foreign.hdlc_state\n");
432 return;
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;
444 static void
445 Bchan_manl1(struct PStack *st, int pr,
446 void *arg)
448 switch (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);
453 break;
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);
458 break;
463 setstack_foreign(struct PStack *st, struct BCState *bcs)
465 if (Bchan_open(bcs))
466 return (-1);
467 st->l1.bcs = bcs;
468 st->l2.l2l1 = Bchan_l2l1;
469 st->ma.manl1 = Bchan_manl1;
470 setstack_manager(st);
471 bcs->st = st;
472 return (0);
476 static void
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};
481 struct sk_buff *skb;
483 /* NOTE: This function is called directly from an interrupt handler */
485 if (1) {
486 if (!(skb = alloc_skb(count, GFP_ATOMIC)))
487 printk(KERN_WARNING "HiSax: D receive out of memory\n");
488 else {
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) {
499 char tmp[128];
500 char *t = tmp;
502 t += sprintf(t, "foreign Drecv cnt %d", count);
503 if (error) t += sprintf(t, " ERR %x", error);
504 QuickHex(t, cs->rcvbuf, count);
505 debugl1(cs, tmp);
508 cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
509 &foreign_drecv_callback, cs);
512 static void
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) {
523 char tmp[128];
524 char *t = tmp;
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);
529 debugl1(cs, tmp);
532 cs->tx_skb = NULL;
534 task.data = (void *) cs;
535 queue_task(&task, &tq_immediate);
536 mark_bh(IMMEDIATE_BH);
539 static void
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;
544 char str[64];
546 switch (pr) {
547 case (PH_DATA_REQ):
548 if (cs->tx_skb) {
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);
553 #endif
554 } else {
555 if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
556 /* I-FRAME */
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,
560 str);
562 cs->tx_skb = skb;
563 cs->tx_cnt = 0;
564 #ifdef L2FRAME_DEBUG /* psa */
565 if (cs->debug & L1_DEB_LAPD)
566 Logl2Frame(cs, skb, "PH_DATA", 0);
567 #endif
568 cs->hw.foreign->dxmit(0, skb->data, skb->len,
569 &foreign_dxmit_callback, cs);
571 break;
572 case (PH_PULL_IND):
573 if (cs->tx_skb) {
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);
577 break;
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,
583 str);
585 cs->tx_skb = skb;
586 cs->tx_cnt = 0;
587 #ifdef L2FRAME_DEBUG /* psa */
588 if (cs->debug & L1_DEB_LAPD)
589 Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
590 #endif
591 cs->hw.foreign->dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
592 &foreign_dxmit_callback, cs);
593 break;
594 case (PH_PULL_REQ):
595 #ifdef L2FRAME_DEBUG /* psa */
596 if (cs->debug & L1_DEB_LAPD)
597 debugl1(cs, "-> PH_REQUEST_PULL");
598 #endif
599 if (!cs->tx_skb) {
600 test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
601 st->l1.l1l2(st, PH_PULL_CNF, NULL);
602 } else
603 test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
604 break;
609 setDstack_foreign(struct PStack *st, struct IsdnCardState *cs)
611 st->l2.l2l1 = foreign_Dchan_l2l1;
612 if (! cs->rcvbuf) {
613 printk("setDstack_foreign: No cs->rcvbuf!\n");
614 } else {
615 cs->hw.foreign->drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
616 &foreign_drecv_callback, cs);
618 return (0);
621 static void
622 manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
623 struct PStack *st;
625 st = cs->stlist;
626 while (st) {
627 st->ma.manl1(st, msg, arg);
628 st = st->next;
632 void
633 foreign_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
635 u_char val;
636 char tmp[32];
638 if (cs->debug & L1_DEB_ISAC) {
639 sprintf(tmp, "foreign_l1cmd msg %x", msg);
640 debugl1(cs, tmp);
643 switch(msg) {
644 case PH_RESET_REQ:
645 cs->hw.foreign->liu_deactivate(0);
646 manl1_msg(cs, PH_POWERUP_CNF, NULL);
647 break;
648 case PH_ENABLE_REQ:
649 break;
650 case PH_INFO3_REQ:
651 cs->hw.foreign->liu_activate(0,0);
652 break;
653 case PH_TESTLOOP_REQ:
654 break;
655 default:
656 if (cs->debug & L1_DEB_WARN) {
657 sprintf(tmp, "foreign_l1cmd unknown %4x", msg);
658 debugl1(cs, tmp);
660 break;
664 static void
665 foreign_new_ph(struct IsdnCardState *cs)
667 switch (cs->hw.foreign->get_liu_state(0)) {
668 case 3:
669 manl1_msg(cs, PH_POWERUP_CNF, NULL);
670 break;
672 case 7:
673 manl1_msg(cs, PH_I4_P8_IND, NULL);
674 break;
676 case 8:
677 manl1_msg(cs, PH_RSYNC_IND, NULL);
678 break;
682 /* LIU state change callback */
684 static void
685 foreign_liu_callback(struct IsdnCardState *cs)
687 static struct tq_struct task = {0, 0, (void *) &foreign_new_ph, 0};
689 if (!cs)
690 return;
692 if (cs->debug & L1_DEB_ISAC) {
693 char tmp[32];
694 sprintf(tmp, "foreign LIU state %d",
695 cs->hw.foreign->get_liu_state(0));
696 debugl1(cs, tmp);
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);
716 static int
717 foreign_card_msg(struct IsdnCardState *cs, int mt, void *arg)
719 switch (mt) {
720 case CARD_RESET:
721 return(0);
722 case CARD_RELEASE:
723 return(0);
724 case CARD_SETIRQ:
725 return(0);
726 case CARD_INIT:
727 cs->l1cmd = foreign_l1cmd;
728 cs->setstack_d = setDstack_foreign;
729 cs->hw.foreign->liu_init(0, &foreign_liu_callback,
730 (void *)cs);
731 init_foreign(cs);
732 return(0);
733 case CARD_TEST:
734 return(0);
736 return(0);
739 #if CARD_AMD7930
740 extern struct foreign_interface amd7930_foreign_interface;
741 #endif
743 #if CARD_DBRI
744 extern struct foreign_interface dbri_foreign_interface;
745 #endif
747 int __init
748 setup_foreign(struct IsdnCard *card)
750 struct IsdnCardState *cs = card->cs;
751 char tmp[64];
753 strcpy(tmp, foreign_revision);
754 printk(KERN_INFO "HiSax: Foreign chip driver Rev. %s\n",
755 HiSax_getrev(tmp));
757 #if CARD_AMD7930
758 if (cs->typ == ISDN_CTYPE_AMD7930) {
759 cs->hw.foreign = &amd7930_foreign_interface;
760 cs->irq = cs->hw.foreign->get_irqnum(0);
761 if (cs->irq == 0)
762 return (0);
763 cs->cardmsg = &foreign_card_msg;
764 return (1);
766 #endif
768 #if CARD_DBRI
769 if (cs->typ == ISDN_CTYPE_DBRI) {
770 cs->hw.foreign = &dbri_foreign_interface;
771 cs->irq = cs->hw.foreign->get_irqnum(0);
772 if (cs->irq == 0)
773 return (0);
774 cs->cardmsg = &foreign_card_msg;
775 return (1);
777 #endif
779 return(0);