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/init.h>
25 #include <linux/netdevice.h>
26 #include "hisax_isac.h"
30 #define __debug_variable debug
31 #include "hisax_debug.h"
33 #ifdef CONFIG_HISAX_DEBUG
35 module_param(debug
, int, 0);
37 static char *ISACVer
[] = {
45 MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
46 MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
47 MODULE_LICENSE("GPL");
49 #define DBG_WARN 0x0001
50 #define DBG_IRQ 0x0002
51 #define DBG_L1M 0x0004
53 #define DBG_RFIFO 0x0100
54 #define DBG_RPACKET 0x0200
55 #define DBG_XFIFO 0x1000
56 #define DBG_XPACKET 0x2000
58 // we need to distinguish ISAC-S and ISAC-SX
59 #define TYPE_ISAC 0x00
60 #define TYPE_ISACSX 0x01
63 #define ISAC_MASK 0x20
64 #define ISAC_ISTA 0x20
65 #define ISAC_ISTA_EXI 0x01
66 #define ISAC_ISTA_SIN 0x02
67 #define ISAC_ISTA_CISQ 0x04
68 #define ISAC_ISTA_XPR 0x10
69 #define ISAC_ISTA_RSC 0x20
70 #define ISAC_ISTA_RPF 0x40
71 #define ISAC_ISTA_RME 0x80
73 #define ISAC_STAR 0x21
74 #define ISAC_CMDR 0x21
75 #define ISAC_CMDR_XRES 0x01
76 #define ISAC_CMDR_XME 0x02
77 #define ISAC_CMDR_XTF 0x08
78 #define ISAC_CMDR_RRES 0x40
79 #define ISAC_CMDR_RMC 0x80
81 #define ISAC_EXIR 0x24
82 #define ISAC_EXIR_MOS 0x04
83 #define ISAC_EXIR_XDU 0x40
84 #define ISAC_EXIR_XMR 0x80
86 #define ISAC_ADF2 0x39
87 #define ISAC_SPCR 0x30
88 #define ISAC_ADF1 0x38
90 #define ISAC_CIR0 0x31
91 #define ISAC_CIX0 0x31
92 #define ISAC_CIR0_CIC0 0x02
93 #define ISAC_CIR0_CIC1 0x01
95 #define ISAC_CIR1 0x33
96 #define ISAC_CIX1 0x33
97 #define ISAC_STCR 0x37
98 #define ISAC_MODE 0x22
100 #define ISAC_RSTA 0x27
101 #define ISAC_RSTA_RDO 0x40
102 #define ISAC_RSTA_CRC 0x20
103 #define ISAC_RSTA_RAB 0x10
105 #define ISAC_RBCL 0x25
106 #define ISAC_RBCH 0x2A
107 #define ISAC_TIMR 0x23
108 #define ISAC_SQXR 0x3b
109 #define ISAC_MOSR 0x3a
110 #define ISAC_MOCR 0x3a
111 #define ISAC_MOR0 0x32
112 #define ISAC_MOX0 0x32
113 #define ISAC_MOR1 0x34
114 #define ISAC_MOX1 0x34
116 #define ISAC_RBCH_XAC 0x80
118 #define ISAC_CMD_TIM 0x0
119 #define ISAC_CMD_RES 0x1
120 #define ISAC_CMD_SSP 0x2
121 #define ISAC_CMD_SCP 0x3
122 #define ISAC_CMD_AR8 0x8
123 #define ISAC_CMD_AR10 0x9
124 #define ISAC_CMD_ARL 0xa
125 #define ISAC_CMD_DI 0xf
127 #define ISACSX_MASK 0x60
128 #define ISACSX_ISTA 0x60
129 #define ISACSX_ISTA_ICD 0x01
130 #define ISACSX_ISTA_CIC 0x10
132 #define ISACSX_MASKD 0x20
133 #define ISACSX_ISTAD 0x20
134 #define ISACSX_ISTAD_XDU 0x04
135 #define ISACSX_ISTAD_XMR 0x08
136 #define ISACSX_ISTAD_XPR 0x10
137 #define ISACSX_ISTAD_RFO 0x20
138 #define ISACSX_ISTAD_RPF 0x40
139 #define ISACSX_ISTAD_RME 0x80
141 #define ISACSX_CMDRD 0x21
142 #define ISACSX_CMDRD_XRES 0x01
143 #define ISACSX_CMDRD_XME 0x02
144 #define ISACSX_CMDRD_XTF 0x08
145 #define ISACSX_CMDRD_RRES 0x40
146 #define ISACSX_CMDRD_RMC 0x80
148 #define ISACSX_MODED 0x22
150 #define ISACSX_RBCLD 0x26
152 #define ISACSX_RSTAD 0x28
153 #define ISACSX_RSTAD_RAB 0x10
154 #define ISACSX_RSTAD_CRC 0x20
155 #define ISACSX_RSTAD_RDO 0x40
156 #define ISACSX_RSTAD_VFR 0x80
158 #define ISACSX_CIR0 0x2e
159 #define ISACSX_CIR0_CIC0 0x08
160 #define ISACSX_CIX0 0x2e
162 #define ISACSX_TR_CONF0 0x30
164 #define ISACSX_TR_CONF2 0x32
166 static struct Fsm l1fsm
;
180 #define L1_STATE_COUNT (ST_L1_F8+1)
182 static char *strL1State
[] =
187 "ST_L1_F3_PEND_DEACT",
213 EV_PH_DEACTIVATE_REQ
,
217 #define L1_EVENT_COUNT (EV_TIMER3 + 1)
219 static char *strL1Event
[] =
234 "EV_PH_AI10", // 1101
237 "EV_PH_ACTIVATE_REQ",
238 "EV_PH_DEACTIVATE_REQ",
242 static inline void D_L1L2(struct isac
*isac
, int pr
, void *arg
)
244 struct hisax_if
*ifc
= (struct hisax_if
*) &isac
->hisax_d_if
;
246 DBG(DBG_PR
, "pr %#x", pr
);
247 ifc
->l1l2(ifc
, pr
, arg
);
250 static void ph_command(struct isac
*isac
, unsigned int command
)
252 DBG(DBG_L1M
, "ph_command %#x", command
);
253 switch (isac
->type
) {
255 isac
->write_isac(isac
, ISAC_CIX0
, (command
<< 2) | 3);
258 isac
->write_isac(isac
, ISACSX_CIX0
, (command
<< 4) | (7 << 1));
263 // ----------------------------------------------------------------------
265 static void l1_di(struct FsmInst
*fi
, int event
, void *arg
)
267 struct isac
*isac
= fi
->userdata
;
269 FsmChangeState(fi
, ST_L1_RESET
);
270 ph_command(isac
, ISAC_CMD_DI
);
273 static void l1_di_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
275 struct isac
*isac
= fi
->userdata
;
277 FsmChangeState(fi
, ST_L1_RESET
);
278 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
279 ph_command(isac
, ISAC_CMD_DI
);
282 static void l1_go_f3pdown(struct FsmInst
*fi
, int event
, void *arg
)
284 FsmChangeState(fi
, ST_L1_F3_PDOWN
);
287 static void l1_go_f3pend_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
289 struct isac
*isac
= fi
->userdata
;
291 FsmChangeState(fi
, ST_L1_F3_PEND_DEACT
);
292 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
293 ph_command(isac
, ISAC_CMD_DI
);
296 static void l1_go_f3pend(struct FsmInst
*fi
, int event
, void *arg
)
298 struct isac
*isac
= fi
->userdata
;
300 FsmChangeState(fi
, ST_L1_F3_PEND_DEACT
);
301 ph_command(isac
, ISAC_CMD_DI
);
304 static void l1_go_f4(struct FsmInst
*fi
, int event
, void *arg
)
306 FsmChangeState(fi
, ST_L1_F4
);
309 static void l1_go_f5(struct FsmInst
*fi
, int event
, void *arg
)
311 FsmChangeState(fi
, ST_L1_F5
);
314 static void l1_go_f6(struct FsmInst
*fi
, int event
, void *arg
)
316 FsmChangeState(fi
, ST_L1_F6
);
319 static void l1_go_f6_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
321 struct isac
*isac
= fi
->userdata
;
323 FsmChangeState(fi
, ST_L1_F6
);
324 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
327 static void l1_go_f7_act_ind(struct FsmInst
*fi
, int event
, void *arg
)
329 struct isac
*isac
= fi
->userdata
;
331 FsmDelTimer(&isac
->timer
, 0);
332 FsmChangeState(fi
, ST_L1_F7
);
333 ph_command(isac
, ISAC_CMD_AR8
);
334 D_L1L2(isac
, PH_ACTIVATE
| INDICATION
, NULL
);
337 static void l1_go_f8(struct FsmInst
*fi
, int event
, void *arg
)
339 FsmChangeState(fi
, ST_L1_F8
);
342 static void l1_go_f8_deact_ind(struct FsmInst
*fi
, int event
, void *arg
)
344 struct isac
*isac
= fi
->userdata
;
346 FsmChangeState(fi
, ST_L1_F8
);
347 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
350 static void l1_ar8(struct FsmInst
*fi
, int event
, void *arg
)
352 struct isac
*isac
= fi
->userdata
;
354 FsmRestartTimer(&isac
->timer
, TIMER3_VALUE
, EV_TIMER3
, NULL
, 2);
355 ph_command(isac
, ISAC_CMD_AR8
);
358 static void l1_timer3(struct FsmInst
*fi
, int event
, void *arg
)
360 struct isac
*isac
= fi
->userdata
;
362 ph_command(isac
, ISAC_CMD_DI
);
363 D_L1L2(isac
, PH_DEACTIVATE
| INDICATION
, NULL
);
366 // state machines according to data sheet PSB 2186 / 3186
368 static struct FsmNode L1FnList
[] __initdata
=
370 {ST_L1_RESET
, EV_PH_RES
, l1_di
},
371 {ST_L1_RESET
, EV_PH_EI
, l1_di
},
372 {ST_L1_RESET
, EV_PH_DC
, l1_go_f3pdown
},
373 {ST_L1_RESET
, EV_PH_AR
, l1_go_f6
},
374 {ST_L1_RESET
, EV_PH_AI8
, l1_go_f7_act_ind
},
376 {ST_L1_F3_PDOWN
, EV_PH_RES
, l1_di
},
377 {ST_L1_F3_PDOWN
, EV_PH_EI
, l1_di
},
378 {ST_L1_F3_PDOWN
, EV_PH_AR
, l1_go_f6
},
379 {ST_L1_F3_PDOWN
, EV_PH_RSY
, l1_go_f5
},
380 {ST_L1_F3_PDOWN
, EV_PH_PU
, l1_go_f4
},
381 {ST_L1_F3_PDOWN
, EV_PH_AI8
, l1_go_f7_act_ind
},
382 {ST_L1_F3_PDOWN
, EV_PH_ACTIVATE_REQ
, l1_ar8
},
383 {ST_L1_F3_PDOWN
, EV_TIMER3
, l1_timer3
},
385 {ST_L1_F3_PEND_DEACT
, EV_PH_RES
, l1_di
},
386 {ST_L1_F3_PEND_DEACT
, EV_PH_EI
, l1_di
},
387 {ST_L1_F3_PEND_DEACT
, EV_PH_DC
, l1_go_f3pdown
},
388 {ST_L1_F3_PEND_DEACT
, EV_PH_RSY
, l1_go_f5
},
389 {ST_L1_F3_PEND_DEACT
, EV_PH_AR
, l1_go_f6
},
390 {ST_L1_F3_PEND_DEACT
, EV_PH_AI8
, l1_go_f7_act_ind
},
392 {ST_L1_F4
, EV_PH_RES
, l1_di
},
393 {ST_L1_F4
, EV_PH_EI
, l1_di
},
394 {ST_L1_F4
, EV_PH_RSY
, l1_go_f5
},
395 {ST_L1_F4
, EV_PH_AI8
, l1_go_f7_act_ind
},
396 {ST_L1_F4
, EV_TIMER3
, l1_timer3
},
397 {ST_L1_F4
, EV_PH_DC
, l1_go_f3pdown
},
399 {ST_L1_F5
, EV_PH_RES
, l1_di
},
400 {ST_L1_F5
, EV_PH_EI
, l1_di
},
401 {ST_L1_F5
, EV_PH_AR
, l1_go_f6
},
402 {ST_L1_F5
, EV_PH_AI8
, l1_go_f7_act_ind
},
403 {ST_L1_F5
, EV_TIMER3
, l1_timer3
},
404 {ST_L1_F5
, EV_PH_DR
, l1_go_f3pend
},
405 {ST_L1_F5
, EV_PH_DC
, l1_go_f3pdown
},
407 {ST_L1_F6
, EV_PH_RES
, l1_di
},
408 {ST_L1_F6
, EV_PH_EI
, l1_di
},
409 {ST_L1_F6
, EV_PH_RSY
, l1_go_f8
},
410 {ST_L1_F6
, EV_PH_AI8
, l1_go_f7_act_ind
},
411 {ST_L1_F6
, EV_PH_DR6
, l1_go_f3pend
},
412 {ST_L1_F6
, EV_TIMER3
, l1_timer3
},
413 {ST_L1_F6
, EV_PH_DC
, l1_go_f3pdown
},
415 {ST_L1_F7
, EV_PH_RES
, l1_di_deact_ind
},
416 {ST_L1_F7
, EV_PH_EI
, l1_di_deact_ind
},
417 {ST_L1_F7
, EV_PH_AR
, l1_go_f6_deact_ind
},
418 {ST_L1_F7
, EV_PH_RSY
, l1_go_f8_deact_ind
},
419 {ST_L1_F7
, EV_PH_DR
, l1_go_f3pend_deact_ind
},
421 {ST_L1_F8
, EV_PH_RES
, l1_di
},
422 {ST_L1_F8
, EV_PH_EI
, l1_di
},
423 {ST_L1_F8
, EV_PH_AR
, l1_go_f6
},
424 {ST_L1_F8
, EV_PH_DR
, l1_go_f3pend
},
425 {ST_L1_F8
, EV_PH_AI8
, l1_go_f7_act_ind
},
426 {ST_L1_F8
, EV_TIMER3
, l1_timer3
},
427 {ST_L1_F8
, EV_PH_DC
, l1_go_f3pdown
},
430 static void l1m_debug(struct FsmInst
*fi
, char *fmt
, ...)
436 vsprintf(buf
, fmt
, args
);
437 DBG(DBG_L1M
, "%s", buf
);
441 static void isac_version(struct isac
*cs
)
445 val
= cs
->read_isac(cs
, ISAC_RBCH
);
446 DBG(1, "ISAC version (%x): %s", val
, ISACVer
[(val
>> 5) & 3]);
449 static void isac_empty_fifo(struct isac
*isac
, int count
)
451 // this also works for isacsx, since
452 // CMDR(D) register works the same
455 DBG(DBG_IRQ
, "count %d", count
);
457 if ((isac
->rcvidx
+ count
) >= MAX_DFRAME_LEN_L1
) {
458 DBG(DBG_WARN
, "overrun %d", isac
->rcvidx
+ count
);
459 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
463 ptr
= isac
->rcvbuf
+ isac
->rcvidx
;
464 isac
->rcvidx
+= count
;
465 isac
->read_isac_fifo(isac
, ptr
, count
);
466 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
467 DBG_PACKET(DBG_RFIFO
, ptr
, count
);
470 static void isac_fill_fifo(struct isac
*isac
)
472 // this also works for isacsx, since
473 // CMDR(D) register works the same
482 count
= isac
->tx_skb
->len
;
486 DBG(DBG_IRQ
, "count %d", count
);
492 cmd
= ISAC_CMDR_XTF
| ISAC_CMDR_XME
;
495 ptr
= isac
->tx_skb
->data
;
496 skb_pull(isac
->tx_skb
, count
);
497 isac
->tx_cnt
+= count
;
498 DBG_PACKET(DBG_XFIFO
, ptr
, count
);
499 isac
->write_isac_fifo(isac
, ptr
, count
);
500 isac
->write_isac(isac
, ISAC_CMDR
, cmd
);
503 static void isac_retransmit(struct isac
*isac
)
506 DBG(DBG_WARN
, "no skb");
509 skb_push(isac
->tx_skb
, isac
->tx_cnt
);
514 static inline void isac_cisq_interrupt(struct isac
*isac
)
518 val
= isac
->read_isac(isac
, ISAC_CIR0
);
519 DBG(DBG_IRQ
, "CIR0 %#x", val
);
520 if (val
& ISAC_CIR0_CIC0
) {
521 DBG(DBG_IRQ
, "CODR0 %#x", (val
>> 2) & 0xf);
522 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
524 if (val
& ISAC_CIR0_CIC1
) {
525 val
= isac
->read_isac(isac
, ISAC_CIR1
);
526 DBG(DBG_WARN
, "ISAC CIR1 %#x", val
);
530 static inline void isac_rme_interrupt(struct isac
*isac
)
536 val
= isac
->read_isac(isac
, ISAC_RSTA
);
537 if ((val
& (ISAC_RSTA_RDO
| ISAC_RSTA_CRC
| ISAC_RSTA_RAB
) )
539 DBG(DBG_WARN
, "RSTA %#x, dropped", val
);
540 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
544 count
= isac
->read_isac(isac
, ISAC_RBCL
) & 0x1f;
545 DBG(DBG_IRQ
, "RBCL %#x", count
);
549 isac_empty_fifo(isac
, count
);
550 count
= isac
->rcvidx
;
552 DBG(DBG_WARN
, "count %d < 1", count
);
556 skb
= alloc_skb(count
, GFP_ATOMIC
);
558 DBG(DBG_WARN
, "no memory, dropping\n");
561 memcpy(skb_put(skb
, count
), isac
->rcvbuf
, count
);
562 DBG_SKB(DBG_RPACKET
, skb
);
563 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
568 static inline void isac_xpr_interrupt(struct isac
*isac
)
573 if (isac
->tx_skb
->len
> 0) {
574 isac_fill_fifo(isac
);
577 dev_kfree_skb_irq(isac
->tx_skb
);
580 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
583 static inline void isac_exi_interrupt(struct isac
*isac
)
587 val
= isac
->read_isac(isac
, ISAC_EXIR
);
588 DBG(2, "EXIR %#x", val
);
590 if (val
& ISAC_EXIR_XMR
) {
591 DBG(DBG_WARN
, "ISAC XMR");
592 isac_retransmit(isac
);
594 if (val
& ISAC_EXIR_XDU
) {
595 DBG(DBG_WARN
, "ISAC XDU");
596 isac_retransmit(isac
);
598 if (val
& ISAC_EXIR_MOS
) { /* MOS */
599 DBG(DBG_WARN
, "MOS");
600 val
= isac
->read_isac(isac
, ISAC_MOSR
);
601 DBG(2, "ISAC MOSR %#x", val
);
605 void isac_irq(struct isac
*isac
)
609 val
= isac
->read_isac(isac
, ISAC_ISTA
);
610 DBG(DBG_IRQ
, "ISTA %#x", val
);
612 if (val
& ISAC_ISTA_EXI
) {
614 isac_exi_interrupt(isac
);
616 if (val
& ISAC_ISTA_XPR
) {
618 isac_xpr_interrupt(isac
);
620 if (val
& ISAC_ISTA_RME
) {
622 isac_rme_interrupt(isac
);
624 if (val
& ISAC_ISTA_RPF
) {
626 isac_empty_fifo(isac
, 0x20);
628 if (val
& ISAC_ISTA_CISQ
) {
629 DBG(DBG_IRQ
, "CISQ");
630 isac_cisq_interrupt(isac
);
632 if (val
& ISAC_ISTA_RSC
) {
633 DBG(DBG_WARN
, "RSC");
635 if (val
& ISAC_ISTA_SIN
) {
636 DBG(DBG_WARN
, "SIN");
638 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
639 isac
->write_isac(isac
, ISAC_MASK
, 0x00);
642 // ======================================================================
644 static inline void isacsx_cic_interrupt(struct isac
*isac
)
648 val
= isac
->read_isac(isac
, ISACSX_CIR0
);
649 DBG(DBG_IRQ
, "CIR0 %#x", val
);
650 if (val
& ISACSX_CIR0_CIC0
) {
651 DBG(DBG_IRQ
, "CODR0 %#x", val
>> 4);
652 FsmEvent(&isac
->l1m
, val
>> 4, NULL
);
656 static inline void isacsx_rme_interrupt(struct isac
*isac
)
662 val
= isac
->read_isac(isac
, ISACSX_RSTAD
);
663 if ((val
& (ISACSX_RSTAD_VFR
|
667 != (ISACSX_RSTAD_VFR
| ISACSX_RSTAD_CRC
)) {
668 DBG(DBG_WARN
, "RSTAD %#x, dropped", val
);
669 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
673 count
= isac
->read_isac(isac
, ISACSX_RBCLD
) & 0x1f;
674 DBG(DBG_IRQ
, "RBCLD %#x", count
);
678 isac_empty_fifo(isac
, count
);
679 // strip trailing status byte
680 count
= isac
->rcvidx
- 1;
682 DBG(DBG_WARN
, "count %d < 1", count
);
686 skb
= dev_alloc_skb(count
);
688 DBG(DBG_WARN
, "no memory, dropping");
691 memcpy(skb_put(skb
, count
), isac
->rcvbuf
, count
);
692 DBG_SKB(DBG_RPACKET
, skb
);
693 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
698 static inline void isacsx_xpr_interrupt(struct isac
*isac
)
703 if (isac
->tx_skb
->len
> 0) {
704 isac_fill_fifo(isac
);
707 dev_kfree_skb_irq(isac
->tx_skb
);
710 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
713 static inline void isacsx_icd_interrupt(struct isac
*isac
)
717 val
= isac
->read_isac(isac
, ISACSX_ISTAD
);
718 DBG(DBG_IRQ
, "ISTAD %#x", val
);
719 if (val
& ISACSX_ISTAD_XDU
) {
720 DBG(DBG_WARN
, "ISTAD XDU");
721 isac_retransmit(isac
);
723 if (val
& ISACSX_ISTAD_XMR
) {
724 DBG(DBG_WARN
, "ISTAD XMR");
725 isac_retransmit(isac
);
727 if (val
& ISACSX_ISTAD_XPR
) {
728 DBG(DBG_IRQ
, "ISTAD XPR");
729 isacsx_xpr_interrupt(isac
);
731 if (val
& ISACSX_ISTAD_RFO
) {
732 DBG(DBG_WARN
, "ISTAD RFO");
733 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
735 if (val
& ISACSX_ISTAD_RME
) {
736 DBG(DBG_IRQ
, "ISTAD RME");
737 isacsx_rme_interrupt(isac
);
739 if (val
& ISACSX_ISTAD_RPF
) {
740 DBG(DBG_IRQ
, "ISTAD RPF");
741 isac_empty_fifo(isac
, 0x20);
745 void isacsx_irq(struct isac
*isac
)
749 val
= isac
->read_isac(isac
, ISACSX_ISTA
);
750 DBG(DBG_IRQ
, "ISTA %#x", val
);
752 if (val
& ISACSX_ISTA_ICD
)
753 isacsx_icd_interrupt(isac
);
754 if (val
& ISACSX_ISTA_CIC
)
755 isacsx_cic_interrupt(isac
);
758 void isac_init(struct isac
*isac
)
761 isac
->l1m
.fsm
= &l1fsm
;
762 isac
->l1m
.state
= ST_L1_RESET
;
763 #ifdef CONFIG_HISAX_DEBUG
768 isac
->l1m
.userdata
= isac
;
769 isac
->l1m
.printdebug
= l1m_debug
;
770 FsmInitTimer(&isac
->l1m
, &isac
->timer
);
773 void isac_setup(struct isac
*isac
)
777 isac
->type
= TYPE_ISAC
;
780 ph_command(isac
, ISAC_CMD_RES
);
782 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
784 if (test_bit(ISAC_IOM1
, &isac
->flags
)) {
786 isac
->write_isac(isac
, ISAC_ADF2
, 0x0);
787 isac
->write_isac(isac
, ISAC_SPCR
, 0xa);
788 isac
->write_isac(isac
, ISAC_ADF1
, 0x2);
789 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
790 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
795 isac
->write_isac(isac
, ISAC_ADF2
, isac
->adf2
);
796 isac
->write_isac(isac
, ISAC_SQXR
, 0x2f);
797 isac
->write_isac(isac
, ISAC_SPCR
, 0x00);
798 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
799 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
800 isac
->write_isac(isac
, ISAC_TIMR
, 0x00);
801 isac
->write_isac(isac
, ISAC_ADF1
, 0x00);
803 val
= isac
->read_isac(isac
, ISAC_STAR
);
804 DBG(2, "ISAC STAR %x", val
);
805 val
= isac
->read_isac(isac
, ISAC_MODE
);
806 DBG(2, "ISAC MODE %x", val
);
807 val
= isac
->read_isac(isac
, ISAC_ADF2
);
808 DBG(2, "ISAC ADF2 %x", val
);
809 val
= isac
->read_isac(isac
, ISAC_ISTA
);
810 DBG(2, "ISAC ISTA %x", val
);
812 eval
= isac
->read_isac(isac
, ISAC_EXIR
);
813 DBG(2, "ISAC EXIR %x", eval
);
815 val
= isac
->read_isac(isac
, ISAC_CIR0
);
816 DBG(2, "ISAC CIR0 %x", val
);
817 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
819 isac
->write_isac(isac
, ISAC_MASK
, 0x0);
820 // RESET Receiver and Transmitter
821 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_XRES
| ISAC_CMDR_RRES
);
824 void isacsx_setup(struct isac
*isac
)
826 isac
->type
= TYPE_ISACSX
;
828 isac
->write_isac(isac
, ISACSX_TR_CONF0
, 0x00);
829 // enable transmitter
830 isac
->write_isac(isac
, ISACSX_TR_CONF2
, 0x00);
831 // transparent mode 0, RAC, stop/go
832 isac
->write_isac(isac
, ISACSX_MODED
, 0xc9);
833 // all HDLC IRQ unmasked
834 isac
->write_isac(isac
, ISACSX_MASKD
, 0x03);
835 // unmask ICD, CID IRQs
836 isac
->write_isac(isac
, ISACSX_MASK
,
837 ~(ISACSX_ISTA_ICD
| ISACSX_ISTA_CIC
));
840 void isac_d_l2l1(struct hisax_if
*hisax_d_if
, int pr
, void *arg
)
842 struct isac
*isac
= hisax_d_if
->priv
;
843 struct sk_buff
*skb
= arg
;
845 DBG(DBG_PR
, "pr %#x", pr
);
848 case PH_ACTIVATE
| REQUEST
:
849 FsmEvent(&isac
->l1m
, EV_PH_ACTIVATE_REQ
, NULL
);
851 case PH_DEACTIVATE
| REQUEST
:
852 FsmEvent(&isac
->l1m
, EV_PH_DEACTIVATE_REQ
, NULL
);
854 case PH_DATA
| REQUEST
:
855 DBG(DBG_PR
, "PH_DATA REQUEST len %d", skb
->len
);
856 DBG_SKB(DBG_XPACKET
, skb
);
857 if (isac
->l1m
.state
!= ST_L1_F7
) {
858 DBG(1, "L1 wrong state %d\n", isac
->l1m
.state
);
866 isac_fill_fifo(isac
);
871 static int __init
hisax_isac_init(void)
873 printk(KERN_INFO
"hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");
875 l1fsm
.state_count
= L1_STATE_COUNT
;
876 l1fsm
.event_count
= L1_EVENT_COUNT
;
877 l1fsm
.strState
= strL1State
;
878 l1fsm
.strEvent
= strL1Event
;
879 return FsmNew(&l1fsm
, L1FnList
, ARRAY_SIZE(L1FnList
));
882 static void __exit
hisax_isac_exit(void)
887 EXPORT_SYMBOL(isac_init
);
888 EXPORT_SYMBOL(isac_d_l2l1
);
890 EXPORT_SYMBOL(isacsx_setup
);
891 EXPORT_SYMBOL(isacsx_irq
);
893 EXPORT_SYMBOL(isac_setup
);
894 EXPORT_SYMBOL(isac_irq
);
896 module_init(hisax_isac_init
);
897 module_exit(hisax_isac_exit
);