2 * Driver for ISAC-S and ISAC-SX
3 * ISDN Subscriber Access Controller for Terminals
5 * Author Kai Germaschewski
6 * Copyright 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
7 * 2001 by Karsten Keil <keil@isdn4linux.de>
9 * based upon Karsten Keil's original isac.c driver
11 * This software may be used and distributed according to the terms
12 * of the GNU General Public License, incorporated herein by reference.
14 * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
15 * SoHaNet Technology GmbH, Berlin
16 * for supporting the development of this driver
20 * specifically handle level vs edge triggered?
23 #include <linux/module.h>
24 #include <linux/gfp.h>
25 #include <linux/init.h>
26 #include <linux/netdevice.h>
27 #include "hisax_isac.h"
31 #define __debug_variable debug
32 #include "hisax_debug.h"
34 #ifdef CONFIG_HISAX_DEBUG
36 module_param(debug
, int, 0);
38 static char *ISACVer
[] = {
46 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
47 MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
48 MODULE_LICENSE("GPL");
50 #define DBG_WARN 0x0001
51 #define DBG_IRQ 0x0002
52 #define DBG_L1M 0x0004
54 #define DBG_RFIFO 0x0100
55 #define DBG_RPACKET 0x0200
56 #define DBG_XFIFO 0x1000
57 #define DBG_XPACKET 0x2000
59 // we need to distinguish ISAC-S and ISAC-SX
60 #define TYPE_ISAC 0x00
61 #define TYPE_ISACSX 0x01
64 #define ISAC_MASK 0x20
65 #define ISAC_ISTA 0x20
66 #define ISAC_ISTA_EXI 0x01
67 #define ISAC_ISTA_SIN 0x02
68 #define ISAC_ISTA_CISQ 0x04
69 #define ISAC_ISTA_XPR 0x10
70 #define ISAC_ISTA_RSC 0x20
71 #define ISAC_ISTA_RPF 0x40
72 #define ISAC_ISTA_RME 0x80
74 #define ISAC_STAR 0x21
75 #define ISAC_CMDR 0x21
76 #define ISAC_CMDR_XRES 0x01
77 #define ISAC_CMDR_XME 0x02
78 #define ISAC_CMDR_XTF 0x08
79 #define ISAC_CMDR_RRES 0x40
80 #define ISAC_CMDR_RMC 0x80
82 #define ISAC_EXIR 0x24
83 #define ISAC_EXIR_MOS 0x04
84 #define ISAC_EXIR_XDU 0x40
85 #define ISAC_EXIR_XMR 0x80
87 #define ISAC_ADF2 0x39
88 #define ISAC_SPCR 0x30
89 #define ISAC_ADF1 0x38
91 #define ISAC_CIR0 0x31
92 #define ISAC_CIX0 0x31
93 #define ISAC_CIR0_CIC0 0x02
94 #define ISAC_CIR0_CIC1 0x01
96 #define ISAC_CIR1 0x33
97 #define ISAC_CIX1 0x33
98 #define ISAC_STCR 0x37
99 #define ISAC_MODE 0x22
101 #define ISAC_RSTA 0x27
102 #define ISAC_RSTA_RDO 0x40
103 #define ISAC_RSTA_CRC 0x20
104 #define ISAC_RSTA_RAB 0x10
106 #define ISAC_RBCL 0x25
107 #define ISAC_RBCH 0x2A
108 #define ISAC_TIMR 0x23
109 #define ISAC_SQXR 0x3b
110 #define ISAC_MOSR 0x3a
111 #define ISAC_MOCR 0x3a
112 #define ISAC_MOR0 0x32
113 #define ISAC_MOX0 0x32
114 #define ISAC_MOR1 0x34
115 #define ISAC_MOX1 0x34
117 #define ISAC_RBCH_XAC 0x80
119 #define ISAC_CMD_TIM 0x0
120 #define ISAC_CMD_RES 0x1
121 #define ISAC_CMD_SSP 0x2
122 #define ISAC_CMD_SCP 0x3
123 #define ISAC_CMD_AR8 0x8
124 #define ISAC_CMD_AR10 0x9
125 #define ISAC_CMD_ARL 0xa
126 #define ISAC_CMD_DI 0xf
128 #define ISACSX_MASK 0x60
129 #define ISACSX_ISTA 0x60
130 #define ISACSX_ISTA_ICD 0x01
131 #define ISACSX_ISTA_CIC 0x10
133 #define ISACSX_MASKD 0x20
134 #define ISACSX_ISTAD 0x20
135 #define ISACSX_ISTAD_XDU 0x04
136 #define ISACSX_ISTAD_XMR 0x08
137 #define ISACSX_ISTAD_XPR 0x10
138 #define ISACSX_ISTAD_RFO 0x20
139 #define ISACSX_ISTAD_RPF 0x40
140 #define ISACSX_ISTAD_RME 0x80
142 #define ISACSX_CMDRD 0x21
143 #define ISACSX_CMDRD_XRES 0x01
144 #define ISACSX_CMDRD_XME 0x02
145 #define ISACSX_CMDRD_XTF 0x08
146 #define ISACSX_CMDRD_RRES 0x40
147 #define ISACSX_CMDRD_RMC 0x80
149 #define ISACSX_MODED 0x22
151 #define ISACSX_RBCLD 0x26
153 #define ISACSX_RSTAD 0x28
154 #define ISACSX_RSTAD_RAB 0x10
155 #define ISACSX_RSTAD_CRC 0x20
156 #define ISACSX_RSTAD_RDO 0x40
157 #define ISACSX_RSTAD_VFR 0x80
159 #define ISACSX_CIR0 0x2e
160 #define ISACSX_CIR0_CIC0 0x08
161 #define ISACSX_CIX0 0x2e
163 #define ISACSX_TR_CONF0 0x30
165 #define ISACSX_TR_CONF2 0x32
167 static struct Fsm l1fsm
;
181 #define L1_STATE_COUNT (ST_L1_F8 + 1)
183 static char *strL1State
[] =
188 "ST_L1_F3_PEND_DEACT",
214 EV_PH_DEACTIVATE_REQ
,
218 #define L1_EVENT_COUNT (EV_TIMER3 + 1)
220 static char *strL1Event
[] =
235 "EV_PH_AI10", // 1101
238 "EV_PH_ACTIVATE_REQ",
239 "EV_PH_DEACTIVATE_REQ",
243 static inline void D_L1L2(struct isac
*isac
, int pr
, void *arg
)
245 struct hisax_if
*ifc
= (struct hisax_if
*) &isac
->hisax_d_if
;
247 DBG(DBG_PR
, "pr %#x", pr
);
248 ifc
->l1l2(ifc
, pr
, arg
);
251 static void ph_command(struct isac
*isac
, unsigned int command
)
253 DBG(DBG_L1M
, "ph_command %#x", command
);
254 switch (isac
->type
) {
256 isac
->write_isac(isac
, ISAC_CIX0
, (command
<< 2) | 3);
259 isac
->write_isac(isac
, ISACSX_CIX0
, (command
<< 4) | (7 << 1));
264 // ----------------------------------------------------------------------
266 static void l1_di(struct FsmInst
*fi
, int event
, void *arg
)
268 struct isac
*isac
= fi
->userdata
;
270 FsmChangeState(fi
, ST_L1_RESET
);
271 ph_command(isac
, ISAC_CMD_DI
);
274 static void l1_di_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
276 struct isac
*isac
= fi
->userdata
;
278 FsmChangeState(fi
, ST_L1_RESET
);
279 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
280 ph_command(isac
, ISAC_CMD_DI
);
283 static void l1_go_f3pdown(struct FsmInst
*fi
, int event
, void *arg
)
285 FsmChangeState(fi
, ST_L1_F3_PDOWN
);
288 static void l1_go_f3pend_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
290 struct isac
*isac
= fi
->userdata
;
292 FsmChangeState(fi
, ST_L1_F3_PEND_DEACT
);
293 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
294 ph_command(isac
, ISAC_CMD_DI
);
297 static void l1_go_f3pend(struct FsmInst
*fi
, int event
, void *arg
)
299 struct isac
*isac
= fi
->userdata
;
301 FsmChangeState(fi
, ST_L1_F3_PEND_DEACT
);
302 ph_command(isac
, ISAC_CMD_DI
);
305 static void l1_go_f4(struct FsmInst
*fi
, int event
, void *arg
)
307 FsmChangeState(fi
, ST_L1_F4
);
310 static void l1_go_f5(struct FsmInst
*fi
, int event
, void *arg
)
312 FsmChangeState(fi
, ST_L1_F5
);
315 static void l1_go_f6(struct FsmInst
*fi
, int event
, void *arg
)
317 FsmChangeState(fi
, ST_L1_F6
);
320 static void l1_go_f6_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
322 struct isac
*isac
= fi
->userdata
;
324 FsmChangeState(fi
, ST_L1_F6
);
325 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
328 static void l1_go_f7_act_ind(struct FsmInst
*fi
, int event
, void *arg
)
330 struct isac
*isac
= fi
->userdata
;
332 FsmDelTimer(&isac
->timer
, 0);
333 FsmChangeState(fi
, ST_L1_F7
);
334 ph_command(isac
, ISAC_CMD_AR8
);
335 D_L1L2(isac
, PH_ACTIVATE
| INDICATION
, NULL
);
338 static void l1_go_f8(struct FsmInst
*fi
, int event
, void *arg
)
340 FsmChangeState(fi
, ST_L1_F8
);
343 static void l1_go_f8_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
345 struct isac
*isac
= fi
->userdata
;
347 FsmChangeState(fi
, ST_L1_F8
);
348 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
351 static void l1_ar8(struct FsmInst
*fi
, int event
, void *arg
)
353 struct isac
*isac
= fi
->userdata
;
355 FsmRestartTimer(&isac
->timer
, TIMER3_VALUE
, EV_TIMER3
, NULL
, 2);
356 ph_command(isac
, ISAC_CMD_AR8
);
359 static void l1_timer3(struct FsmInst
*fi
, int event
, void *arg
)
361 struct isac
*isac
= fi
->userdata
;
363 ph_command(isac
, ISAC_CMD_DI
);
364 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
367 // state machines according to data sheet PSB 2186 / 3186
369 static struct FsmNode L1FnList
[] __initdata
=
371 {ST_L1_RESET
, EV_PH_RES
, l1_di
},
372 {ST_L1_RESET
, EV_PH_EI
, l1_di
},
373 {ST_L1_RESET
, EV_PH_DC
, l1_go_f3pdown
},
374 {ST_L1_RESET
, EV_PH_AR
, l1_go_f6
},
375 {ST_L1_RESET
, EV_PH_AI8
, l1_go_f7_act_ind
},
377 {ST_L1_F3_PDOWN
, EV_PH_RES
, l1_di
},
378 {ST_L1_F3_PDOWN
, EV_PH_EI
, l1_di
},
379 {ST_L1_F3_PDOWN
, EV_PH_AR
, l1_go_f6
},
380 {ST_L1_F3_PDOWN
, EV_PH_RSY
, l1_go_f5
},
381 {ST_L1_F3_PDOWN
, EV_PH_PU
, l1_go_f4
},
382 {ST_L1_F3_PDOWN
, EV_PH_AI8
, l1_go_f7_act_ind
},
383 {ST_L1_F3_PDOWN
, EV_PH_ACTIVATE_REQ
, l1_ar8
},
384 {ST_L1_F3_PDOWN
, EV_TIMER3
, l1_timer3
},
386 {ST_L1_F3_PEND_DEACT
, EV_PH_RES
, l1_di
},
387 {ST_L1_F3_PEND_DEACT
, EV_PH_EI
, l1_di
},
388 {ST_L1_F3_PEND_DEACT
, EV_PH_DC
, l1_go_f3pdown
},
389 {ST_L1_F3_PEND_DEACT
, EV_PH_RSY
, l1_go_f5
},
390 {ST_L1_F3_PEND_DEACT
, EV_PH_AR
, l1_go_f6
},
391 {ST_L1_F3_PEND_DEACT
, EV_PH_AI8
, l1_go_f7_act_ind
},
393 {ST_L1_F4
, EV_PH_RES
, l1_di
},
394 {ST_L1_F4
, EV_PH_EI
, l1_di
},
395 {ST_L1_F4
, EV_PH_RSY
, l1_go_f5
},
396 {ST_L1_F4
, EV_PH_AI8
, l1_go_f7_act_ind
},
397 {ST_L1_F4
, EV_TIMER3
, l1_timer3
},
398 {ST_L1_F4
, EV_PH_DC
, l1_go_f3pdown
},
400 {ST_L1_F5
, EV_PH_RES
, l1_di
},
401 {ST_L1_F5
, EV_PH_EI
, l1_di
},
402 {ST_L1_F5
, EV_PH_AR
, l1_go_f6
},
403 {ST_L1_F5
, EV_PH_AI8
, l1_go_f7_act_ind
},
404 {ST_L1_F5
, EV_TIMER3
, l1_timer3
},
405 {ST_L1_F5
, EV_PH_DR
, l1_go_f3pend
},
406 {ST_L1_F5
, EV_PH_DC
, l1_go_f3pdown
},
408 {ST_L1_F6
, EV_PH_RES
, l1_di
},
409 {ST_L1_F6
, EV_PH_EI
, l1_di
},
410 {ST_L1_F6
, EV_PH_RSY
, l1_go_f8
},
411 {ST_L1_F6
, EV_PH_AI8
, l1_go_f7_act_ind
},
412 {ST_L1_F6
, EV_PH_DR6
, l1_go_f3pend
},
413 {ST_L1_F6
, EV_TIMER3
, l1_timer3
},
414 {ST_L1_F6
, EV_PH_DC
, l1_go_f3pdown
},
416 {ST_L1_F7
, EV_PH_RES
, l1_di_deact_ind
},
417 {ST_L1_F7
, EV_PH_EI
, l1_di_deact_ind
},
418 {ST_L1_F7
, EV_PH_AR
, l1_go_f6_deact_ind
},
419 {ST_L1_F7
, EV_PH_RSY
, l1_go_f8_deact_ind
},
420 {ST_L1_F7
, EV_PH_DR
, l1_go_f3pend_deact_ind
},
422 {ST_L1_F8
, EV_PH_RES
, l1_di
},
423 {ST_L1_F8
, EV_PH_EI
, l1_di
},
424 {ST_L1_F8
, EV_PH_AR
, l1_go_f6
},
425 {ST_L1_F8
, EV_PH_DR
, l1_go_f3pend
},
426 {ST_L1_F8
, EV_PH_AI8
, l1_go_f7_act_ind
},
427 {ST_L1_F8
, EV_TIMER3
, l1_timer3
},
428 {ST_L1_F8
, EV_PH_DC
, l1_go_f3pdown
},
431 static void l1m_debug(struct FsmInst
*fi
, char *fmt
, ...)
437 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
438 DBG(DBG_L1M
, "%s", buf
);
442 static void isac_version(struct isac
*cs
)
446 val
= cs
->read_isac(cs
, ISAC_RBCH
);
447 DBG(1, "ISAC version (%x): %s", val
, ISACVer
[(val
>> 5) & 3]);
450 static void isac_empty_fifo(struct isac
*isac
, int count
)
452 // this also works for isacsx, since
453 // CMDR(D) register works the same
456 DBG(DBG_IRQ
, "count %d", count
);
458 if ((isac
->rcvidx
+ count
) >= MAX_DFRAME_LEN_L1
) {
459 DBG(DBG_WARN
, "overrun %d", isac
->rcvidx
+ count
);
460 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
464 ptr
= isac
->rcvbuf
+ isac
->rcvidx
;
465 isac
->rcvidx
+= count
;
466 isac
->read_isac_fifo(isac
, ptr
, count
);
467 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
468 DBG_PACKET(DBG_RFIFO
, ptr
, count
);
471 static void isac_fill_fifo(struct isac
*isac
)
473 // this also works for isacsx, since
474 // CMDR(D) register works the same
480 BUG_ON(!isac
->tx_skb
);
482 count
= isac
->tx_skb
->len
;
485 DBG(DBG_IRQ
, "count %d", count
);
491 cmd
= ISAC_CMDR_XTF
| ISAC_CMDR_XME
;
494 ptr
= isac
->tx_skb
->data
;
495 skb_pull(isac
->tx_skb
, count
);
496 isac
->tx_cnt
+= count
;
497 DBG_PACKET(DBG_XFIFO
, ptr
, count
);
498 isac
->write_isac_fifo(isac
, ptr
, count
);
499 isac
->write_isac(isac
, ISAC_CMDR
, cmd
);
502 static void isac_retransmit(struct isac
*isac
)
505 DBG(DBG_WARN
, "no skb");
508 skb_push(isac
->tx_skb
, isac
->tx_cnt
);
513 static inline void isac_cisq_interrupt(struct isac
*isac
)
517 val
= isac
->read_isac(isac
, ISAC_CIR0
);
518 DBG(DBG_IRQ
, "CIR0 %#x", val
);
519 if (val
& ISAC_CIR0_CIC0
) {
520 DBG(DBG_IRQ
, "CODR0 %#x", (val
>> 2) & 0xf);
521 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
523 if (val
& ISAC_CIR0_CIC1
) {
524 val
= isac
->read_isac(isac
, ISAC_CIR1
);
525 DBG(DBG_WARN
, "ISAC CIR1 %#x", val
);
529 static inline void isac_rme_interrupt(struct isac
*isac
)
535 val
= isac
->read_isac(isac
, ISAC_RSTA
);
536 if ((val
& (ISAC_RSTA_RDO
| ISAC_RSTA_CRC
| ISAC_RSTA_RAB
))
538 DBG(DBG_WARN
, "RSTA %#x, dropped", val
);
539 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
543 count
= isac
->read_isac(isac
, ISAC_RBCL
) & 0x1f;
544 DBG(DBG_IRQ
, "RBCL %#x", count
);
548 isac_empty_fifo(isac
, count
);
549 count
= isac
->rcvidx
;
551 DBG(DBG_WARN
, "count %d < 1", count
);
555 skb
= alloc_skb(count
, GFP_ATOMIC
);
557 DBG(DBG_WARN
, "no memory, dropping\n");
560 skb_put_data(skb
, isac
->rcvbuf
, count
);
561 DBG_SKB(DBG_RPACKET
, skb
);
562 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
567 static inline void isac_xpr_interrupt(struct isac
*isac
)
572 if (isac
->tx_skb
->len
> 0) {
573 isac_fill_fifo(isac
);
576 dev_kfree_skb_irq(isac
->tx_skb
);
579 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
582 static inline void isac_exi_interrupt(struct isac
*isac
)
586 val
= isac
->read_isac(isac
, ISAC_EXIR
);
587 DBG(2, "EXIR %#x", val
);
589 if (val
& ISAC_EXIR_XMR
) {
590 DBG(DBG_WARN
, "ISAC XMR");
591 isac_retransmit(isac
);
593 if (val
& ISAC_EXIR_XDU
) {
594 DBG(DBG_WARN
, "ISAC XDU");
595 isac_retransmit(isac
);
597 if (val
& ISAC_EXIR_MOS
) { /* MOS */
598 DBG(DBG_WARN
, "MOS");
599 val
= isac
->read_isac(isac
, ISAC_MOSR
);
600 DBG(2, "ISAC MOSR %#x", val
);
604 void isac_irq(struct isac
*isac
)
608 val
= isac
->read_isac(isac
, ISAC_ISTA
);
609 DBG(DBG_IRQ
, "ISTA %#x", val
);
611 if (val
& ISAC_ISTA_EXI
) {
613 isac_exi_interrupt(isac
);
615 if (val
& ISAC_ISTA_XPR
) {
617 isac_xpr_interrupt(isac
);
619 if (val
& ISAC_ISTA_RME
) {
621 isac_rme_interrupt(isac
);
623 if (val
& ISAC_ISTA_RPF
) {
625 isac_empty_fifo(isac
, 0x20);
627 if (val
& ISAC_ISTA_CISQ
) {
628 DBG(DBG_IRQ
, "CISQ");
629 isac_cisq_interrupt(isac
);
631 if (val
& ISAC_ISTA_RSC
) {
632 DBG(DBG_WARN
, "RSC");
634 if (val
& ISAC_ISTA_SIN
) {
635 DBG(DBG_WARN
, "SIN");
637 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
638 isac
->write_isac(isac
, ISAC_MASK
, 0x00);
641 // ======================================================================
643 static inline void isacsx_cic_interrupt(struct isac
*isac
)
647 val
= isac
->read_isac(isac
, ISACSX_CIR0
);
648 DBG(DBG_IRQ
, "CIR0 %#x", val
);
649 if (val
& ISACSX_CIR0_CIC0
) {
650 DBG(DBG_IRQ
, "CODR0 %#x", val
>> 4);
651 FsmEvent(&isac
->l1m
, val
>> 4, NULL
);
655 static inline void isacsx_rme_interrupt(struct isac
*isac
)
661 val
= isac
->read_isac(isac
, ISACSX_RSTAD
);
662 if ((val
& (ISACSX_RSTAD_VFR
|
666 != (ISACSX_RSTAD_VFR
| ISACSX_RSTAD_CRC
)) {
667 DBG(DBG_WARN
, "RSTAD %#x, dropped", val
);
668 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
672 count
= isac
->read_isac(isac
, ISACSX_RBCLD
) & 0x1f;
673 DBG(DBG_IRQ
, "RBCLD %#x", count
);
677 isac_empty_fifo(isac
, count
);
678 // strip trailing status byte
679 count
= isac
->rcvidx
- 1;
681 DBG(DBG_WARN
, "count %d < 1", count
);
685 skb
= dev_alloc_skb(count
);
687 DBG(DBG_WARN
, "no memory, dropping");
690 skb_put_data(skb
, isac
->rcvbuf
, count
);
691 DBG_SKB(DBG_RPACKET
, skb
);
692 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
697 static inline void isacsx_xpr_interrupt(struct isac
*isac
)
702 if (isac
->tx_skb
->len
> 0) {
703 isac_fill_fifo(isac
);
706 dev_kfree_skb_irq(isac
->tx_skb
);
709 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
712 static inline void isacsx_icd_interrupt(struct isac
*isac
)
716 val
= isac
->read_isac(isac
, ISACSX_ISTAD
);
717 DBG(DBG_IRQ
, "ISTAD %#x", val
);
718 if (val
& ISACSX_ISTAD_XDU
) {
719 DBG(DBG_WARN
, "ISTAD XDU");
720 isac_retransmit(isac
);
722 if (val
& ISACSX_ISTAD_XMR
) {
723 DBG(DBG_WARN
, "ISTAD XMR");
724 isac_retransmit(isac
);
726 if (val
& ISACSX_ISTAD_XPR
) {
727 DBG(DBG_IRQ
, "ISTAD XPR");
728 isacsx_xpr_interrupt(isac
);
730 if (val
& ISACSX_ISTAD_RFO
) {
731 DBG(DBG_WARN
, "ISTAD RFO");
732 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
734 if (val
& ISACSX_ISTAD_RME
) {
735 DBG(DBG_IRQ
, "ISTAD RME");
736 isacsx_rme_interrupt(isac
);
738 if (val
& ISACSX_ISTAD_RPF
) {
739 DBG(DBG_IRQ
, "ISTAD RPF");
740 isac_empty_fifo(isac
, 0x20);
744 void isacsx_irq(struct isac
*isac
)
748 val
= isac
->read_isac(isac
, ISACSX_ISTA
);
749 DBG(DBG_IRQ
, "ISTA %#x", val
);
751 if (val
& ISACSX_ISTA_ICD
)
752 isacsx_icd_interrupt(isac
);
753 if (val
& ISACSX_ISTA_CIC
)
754 isacsx_cic_interrupt(isac
);
757 void isac_init(struct isac
*isac
)
760 isac
->l1m
.fsm
= &l1fsm
;
761 isac
->l1m
.state
= ST_L1_RESET
;
762 #ifdef CONFIG_HISAX_DEBUG
767 isac
->l1m
.userdata
= isac
;
768 isac
->l1m
.printdebug
= l1m_debug
;
769 FsmInitTimer(&isac
->l1m
, &isac
->timer
);
772 void isac_setup(struct isac
*isac
)
776 isac
->type
= TYPE_ISAC
;
779 ph_command(isac
, ISAC_CMD_RES
);
781 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
783 if (test_bit(ISAC_IOM1
, &isac
->flags
)) {
785 isac
->write_isac(isac
, ISAC_ADF2
, 0x0);
786 isac
->write_isac(isac
, ISAC_SPCR
, 0xa);
787 isac
->write_isac(isac
, ISAC_ADF1
, 0x2);
788 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
789 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
794 isac
->write_isac(isac
, ISAC_ADF2
, isac
->adf2
);
795 isac
->write_isac(isac
, ISAC_SQXR
, 0x2f);
796 isac
->write_isac(isac
, ISAC_SPCR
, 0x00);
797 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
798 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
799 isac
->write_isac(isac
, ISAC_TIMR
, 0x00);
800 isac
->write_isac(isac
, ISAC_ADF1
, 0x00);
802 val
= isac
->read_isac(isac
, ISAC_STAR
);
803 DBG(2, "ISAC STAR %x", val
);
804 val
= isac
->read_isac(isac
, ISAC_MODE
);
805 DBG(2, "ISAC MODE %x", val
);
806 val
= isac
->read_isac(isac
, ISAC_ADF2
);
807 DBG(2, "ISAC ADF2 %x", val
);
808 val
= isac
->read_isac(isac
, ISAC_ISTA
);
809 DBG(2, "ISAC ISTA %x", val
);
811 eval
= isac
->read_isac(isac
, ISAC_EXIR
);
812 DBG(2, "ISAC EXIR %x", eval
);
814 val
= isac
->read_isac(isac
, ISAC_CIR0
);
815 DBG(2, "ISAC CIR0 %x", val
);
816 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
818 isac
->write_isac(isac
, ISAC_MASK
, 0x0);
819 // RESET Receiver and Transmitter
820 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_XRES
| ISAC_CMDR_RRES
);
823 void isacsx_setup(struct isac
*isac
)
825 isac
->type
= TYPE_ISACSX
;
827 isac
->write_isac(isac
, ISACSX_TR_CONF0
, 0x00);
828 // enable transmitter
829 isac
->write_isac(isac
, ISACSX_TR_CONF2
, 0x00);
830 // transparent mode 0, RAC, stop/go
831 isac
->write_isac(isac
, ISACSX_MODED
, 0xc9);
832 // all HDLC IRQ unmasked
833 isac
->write_isac(isac
, ISACSX_MASKD
, 0x03);
834 // unmask ICD, CID IRQs
835 isac
->write_isac(isac
, ISACSX_MASK
,
836 ~(ISACSX_ISTA_ICD
| ISACSX_ISTA_CIC
));
839 void isac_d_l2l1(struct hisax_if
*hisax_d_if
, int pr
, void *arg
)
841 struct isac
*isac
= hisax_d_if
->priv
;
842 struct sk_buff
*skb
= arg
;
844 DBG(DBG_PR
, "pr %#x", pr
);
847 case PH_ACTIVATE
| REQUEST
:
848 FsmEvent(&isac
->l1m
, EV_PH_ACTIVATE_REQ
, NULL
);
850 case PH_DEACTIVATE
| REQUEST
:
851 FsmEvent(&isac
->l1m
, EV_PH_DEACTIVATE_REQ
, NULL
);
853 case PH_DATA
| REQUEST
:
854 DBG(DBG_PR
, "PH_DATA REQUEST len %d", skb
->len
);
855 DBG_SKB(DBG_XPACKET
, skb
);
856 if (isac
->l1m
.state
!= ST_L1_F7
) {
857 DBG(1, "L1 wrong state %d\n", isac
->l1m
.state
);
861 BUG_ON(isac
->tx_skb
);
864 isac_fill_fifo(isac
);
869 static int __init
hisax_isac_init(void)
871 printk(KERN_INFO
"hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");
873 l1fsm
.state_count
= L1_STATE_COUNT
;
874 l1fsm
.event_count
= L1_EVENT_COUNT
;
875 l1fsm
.strState
= strL1State
;
876 l1fsm
.strEvent
= strL1Event
;
877 return FsmNew(&l1fsm
, L1FnList
, ARRAY_SIZE(L1FnList
));
880 static void __exit
hisax_isac_exit(void)
885 EXPORT_SYMBOL(isac_init
);
886 EXPORT_SYMBOL(isac_d_l2l1
);
888 EXPORT_SYMBOL(isacsx_setup
);
889 EXPORT_SYMBOL(isacsx_irq
);
891 EXPORT_SYMBOL(isac_setup
);
892 EXPORT_SYMBOL(isac_irq
);
894 module_init(hisax_isac_init
);
895 module_exit(hisax_isac_exit
);