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 vsnprintf(buf
, sizeof(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
479 BUG_ON(!isac
->tx_skb
);
481 count
= isac
->tx_skb
->len
;
484 DBG(DBG_IRQ
, "count %d", count
);
490 cmd
= ISAC_CMDR_XTF
| ISAC_CMDR_XME
;
493 ptr
= isac
->tx_skb
->data
;
494 skb_pull(isac
->tx_skb
, count
);
495 isac
->tx_cnt
+= count
;
496 DBG_PACKET(DBG_XFIFO
, ptr
, count
);
497 isac
->write_isac_fifo(isac
, ptr
, count
);
498 isac
->write_isac(isac
, ISAC_CMDR
, cmd
);
501 static void isac_retransmit(struct isac
*isac
)
504 DBG(DBG_WARN
, "no skb");
507 skb_push(isac
->tx_skb
, isac
->tx_cnt
);
512 static inline void isac_cisq_interrupt(struct isac
*isac
)
516 val
= isac
->read_isac(isac
, ISAC_CIR0
);
517 DBG(DBG_IRQ
, "CIR0 %#x", val
);
518 if (val
& ISAC_CIR0_CIC0
) {
519 DBG(DBG_IRQ
, "CODR0 %#x", (val
>> 2) & 0xf);
520 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
522 if (val
& ISAC_CIR0_CIC1
) {
523 val
= isac
->read_isac(isac
, ISAC_CIR1
);
524 DBG(DBG_WARN
, "ISAC CIR1 %#x", val
);
528 static inline void isac_rme_interrupt(struct isac
*isac
)
534 val
= isac
->read_isac(isac
, ISAC_RSTA
);
535 if ((val
& (ISAC_RSTA_RDO
| ISAC_RSTA_CRC
| ISAC_RSTA_RAB
) )
537 DBG(DBG_WARN
, "RSTA %#x, dropped", val
);
538 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_RMC
);
542 count
= isac
->read_isac(isac
, ISAC_RBCL
) & 0x1f;
543 DBG(DBG_IRQ
, "RBCL %#x", count
);
547 isac_empty_fifo(isac
, count
);
548 count
= isac
->rcvidx
;
550 DBG(DBG_WARN
, "count %d < 1", count
);
554 skb
= alloc_skb(count
, GFP_ATOMIC
);
556 DBG(DBG_WARN
, "no memory, dropping\n");
559 memcpy(skb_put(skb
, count
), isac
->rcvbuf
, count
);
560 DBG_SKB(DBG_RPACKET
, skb
);
561 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
566 static inline void isac_xpr_interrupt(struct isac
*isac
)
571 if (isac
->tx_skb
->len
> 0) {
572 isac_fill_fifo(isac
);
575 dev_kfree_skb_irq(isac
->tx_skb
);
578 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
581 static inline void isac_exi_interrupt(struct isac
*isac
)
585 val
= isac
->read_isac(isac
, ISAC_EXIR
);
586 DBG(2, "EXIR %#x", val
);
588 if (val
& ISAC_EXIR_XMR
) {
589 DBG(DBG_WARN
, "ISAC XMR");
590 isac_retransmit(isac
);
592 if (val
& ISAC_EXIR_XDU
) {
593 DBG(DBG_WARN
, "ISAC XDU");
594 isac_retransmit(isac
);
596 if (val
& ISAC_EXIR_MOS
) { /* MOS */
597 DBG(DBG_WARN
, "MOS");
598 val
= isac
->read_isac(isac
, ISAC_MOSR
);
599 DBG(2, "ISAC MOSR %#x", val
);
603 void isac_irq(struct isac
*isac
)
607 val
= isac
->read_isac(isac
, ISAC_ISTA
);
608 DBG(DBG_IRQ
, "ISTA %#x", val
);
610 if (val
& ISAC_ISTA_EXI
) {
612 isac_exi_interrupt(isac
);
614 if (val
& ISAC_ISTA_XPR
) {
616 isac_xpr_interrupt(isac
);
618 if (val
& ISAC_ISTA_RME
) {
620 isac_rme_interrupt(isac
);
622 if (val
& ISAC_ISTA_RPF
) {
624 isac_empty_fifo(isac
, 0x20);
626 if (val
& ISAC_ISTA_CISQ
) {
627 DBG(DBG_IRQ
, "CISQ");
628 isac_cisq_interrupt(isac
);
630 if (val
& ISAC_ISTA_RSC
) {
631 DBG(DBG_WARN
, "RSC");
633 if (val
& ISAC_ISTA_SIN
) {
634 DBG(DBG_WARN
, "SIN");
636 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
637 isac
->write_isac(isac
, ISAC_MASK
, 0x00);
640 // ======================================================================
642 static inline void isacsx_cic_interrupt(struct isac
*isac
)
646 val
= isac
->read_isac(isac
, ISACSX_CIR0
);
647 DBG(DBG_IRQ
, "CIR0 %#x", val
);
648 if (val
& ISACSX_CIR0_CIC0
) {
649 DBG(DBG_IRQ
, "CODR0 %#x", val
>> 4);
650 FsmEvent(&isac
->l1m
, val
>> 4, NULL
);
654 static inline void isacsx_rme_interrupt(struct isac
*isac
)
660 val
= isac
->read_isac(isac
, ISACSX_RSTAD
);
661 if ((val
& (ISACSX_RSTAD_VFR
|
665 != (ISACSX_RSTAD_VFR
| ISACSX_RSTAD_CRC
)) {
666 DBG(DBG_WARN
, "RSTAD %#x, dropped", val
);
667 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
671 count
= isac
->read_isac(isac
, ISACSX_RBCLD
) & 0x1f;
672 DBG(DBG_IRQ
, "RBCLD %#x", count
);
676 isac_empty_fifo(isac
, count
);
677 // strip trailing status byte
678 count
= isac
->rcvidx
- 1;
680 DBG(DBG_WARN
, "count %d < 1", count
);
684 skb
= dev_alloc_skb(count
);
686 DBG(DBG_WARN
, "no memory, dropping");
689 memcpy(skb_put(skb
, count
), isac
->rcvbuf
, count
);
690 DBG_SKB(DBG_RPACKET
, skb
);
691 D_L1L2(isac
, PH_DATA
| INDICATION
, skb
);
696 static inline void isacsx_xpr_interrupt(struct isac
*isac
)
701 if (isac
->tx_skb
->len
> 0) {
702 isac_fill_fifo(isac
);
705 dev_kfree_skb_irq(isac
->tx_skb
);
708 D_L1L2(isac
, PH_DATA
| CONFIRM
, NULL
);
711 static inline void isacsx_icd_interrupt(struct isac
*isac
)
715 val
= isac
->read_isac(isac
, ISACSX_ISTAD
);
716 DBG(DBG_IRQ
, "ISTAD %#x", val
);
717 if (val
& ISACSX_ISTAD_XDU
) {
718 DBG(DBG_WARN
, "ISTAD XDU");
719 isac_retransmit(isac
);
721 if (val
& ISACSX_ISTAD_XMR
) {
722 DBG(DBG_WARN
, "ISTAD XMR");
723 isac_retransmit(isac
);
725 if (val
& ISACSX_ISTAD_XPR
) {
726 DBG(DBG_IRQ
, "ISTAD XPR");
727 isacsx_xpr_interrupt(isac
);
729 if (val
& ISACSX_ISTAD_RFO
) {
730 DBG(DBG_WARN
, "ISTAD RFO");
731 isac
->write_isac(isac
, ISACSX_CMDRD
, ISACSX_CMDRD_RMC
);
733 if (val
& ISACSX_ISTAD_RME
) {
734 DBG(DBG_IRQ
, "ISTAD RME");
735 isacsx_rme_interrupt(isac
);
737 if (val
& ISACSX_ISTAD_RPF
) {
738 DBG(DBG_IRQ
, "ISTAD RPF");
739 isac_empty_fifo(isac
, 0x20);
743 void isacsx_irq(struct isac
*isac
)
747 val
= isac
->read_isac(isac
, ISACSX_ISTA
);
748 DBG(DBG_IRQ
, "ISTA %#x", val
);
750 if (val
& ISACSX_ISTA_ICD
)
751 isacsx_icd_interrupt(isac
);
752 if (val
& ISACSX_ISTA_CIC
)
753 isacsx_cic_interrupt(isac
);
756 void isac_init(struct isac
*isac
)
759 isac
->l1m
.fsm
= &l1fsm
;
760 isac
->l1m
.state
= ST_L1_RESET
;
761 #ifdef CONFIG_HISAX_DEBUG
766 isac
->l1m
.userdata
= isac
;
767 isac
->l1m
.printdebug
= l1m_debug
;
768 FsmInitTimer(&isac
->l1m
, &isac
->timer
);
771 void isac_setup(struct isac
*isac
)
775 isac
->type
= TYPE_ISAC
;
778 ph_command(isac
, ISAC_CMD_RES
);
780 isac
->write_isac(isac
, ISAC_MASK
, 0xff);
782 if (test_bit(ISAC_IOM1
, &isac
->flags
)) {
784 isac
->write_isac(isac
, ISAC_ADF2
, 0x0);
785 isac
->write_isac(isac
, ISAC_SPCR
, 0xa);
786 isac
->write_isac(isac
, ISAC_ADF1
, 0x2);
787 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
788 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
793 isac
->write_isac(isac
, ISAC_ADF2
, isac
->adf2
);
794 isac
->write_isac(isac
, ISAC_SQXR
, 0x2f);
795 isac
->write_isac(isac
, ISAC_SPCR
, 0x00);
796 isac
->write_isac(isac
, ISAC_STCR
, 0x70);
797 isac
->write_isac(isac
, ISAC_MODE
, 0xc9);
798 isac
->write_isac(isac
, ISAC_TIMR
, 0x00);
799 isac
->write_isac(isac
, ISAC_ADF1
, 0x00);
801 val
= isac
->read_isac(isac
, ISAC_STAR
);
802 DBG(2, "ISAC STAR %x", val
);
803 val
= isac
->read_isac(isac
, ISAC_MODE
);
804 DBG(2, "ISAC MODE %x", val
);
805 val
= isac
->read_isac(isac
, ISAC_ADF2
);
806 DBG(2, "ISAC ADF2 %x", val
);
807 val
= isac
->read_isac(isac
, ISAC_ISTA
);
808 DBG(2, "ISAC ISTA %x", val
);
810 eval
= isac
->read_isac(isac
, ISAC_EXIR
);
811 DBG(2, "ISAC EXIR %x", eval
);
813 val
= isac
->read_isac(isac
, ISAC_CIR0
);
814 DBG(2, "ISAC CIR0 %x", val
);
815 FsmEvent(&isac
->l1m
, (val
>> 2) & 0xf, NULL
);
817 isac
->write_isac(isac
, ISAC_MASK
, 0x0);
818 // RESET Receiver and Transmitter
819 isac
->write_isac(isac
, ISAC_CMDR
, ISAC_CMDR_XRES
| ISAC_CMDR_RRES
);
822 void isacsx_setup(struct isac
*isac
)
824 isac
->type
= TYPE_ISACSX
;
826 isac
->write_isac(isac
, ISACSX_TR_CONF0
, 0x00);
827 // enable transmitter
828 isac
->write_isac(isac
, ISACSX_TR_CONF2
, 0x00);
829 // transparent mode 0, RAC, stop/go
830 isac
->write_isac(isac
, ISACSX_MODED
, 0xc9);
831 // all HDLC IRQ unmasked
832 isac
->write_isac(isac
, ISACSX_MASKD
, 0x03);
833 // unmask ICD, CID IRQs
834 isac
->write_isac(isac
, ISACSX_MASK
,
835 ~(ISACSX_ISTA_ICD
| ISACSX_ISTA_CIC
));
838 void isac_d_l2l1(struct hisax_if
*hisax_d_if
, int pr
, void *arg
)
840 struct isac
*isac
= hisax_d_if
->priv
;
841 struct sk_buff
*skb
= arg
;
843 DBG(DBG_PR
, "pr %#x", pr
);
846 case PH_ACTIVATE
| REQUEST
:
847 FsmEvent(&isac
->l1m
, EV_PH_ACTIVATE_REQ
, NULL
);
849 case PH_DEACTIVATE
| REQUEST
:
850 FsmEvent(&isac
->l1m
, EV_PH_DEACTIVATE_REQ
, NULL
);
852 case PH_DATA
| REQUEST
:
853 DBG(DBG_PR
, "PH_DATA REQUEST len %d", skb
->len
);
854 DBG_SKB(DBG_XPACKET
, skb
);
855 if (isac
->l1m
.state
!= ST_L1_F7
) {
856 DBG(1, "L1 wrong state %d\n", isac
->l1m
.state
);
860 BUG_ON(isac
->tx_skb
);
863 isac_fill_fifo(isac
);
868 static int __init
hisax_isac_init(void)
870 printk(KERN_INFO
"hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");
872 l1fsm
.state_count
= L1_STATE_COUNT
;
873 l1fsm
.event_count
= L1_EVENT_COUNT
;
874 l1fsm
.strState
= strL1State
;
875 l1fsm
.strEvent
= strL1Event
;
876 return FsmNew(&l1fsm
, L1FnList
, ARRAY_SIZE(L1FnList
));
879 static void __exit
hisax_isac_exit(void)
884 EXPORT_SYMBOL(isac_init
);
885 EXPORT_SYMBOL(isac_d_l2l1
);
887 EXPORT_SYMBOL(isacsx_setup
);
888 EXPORT_SYMBOL(isacsx_irq
);
890 EXPORT_SYMBOL(isac_setup
);
891 EXPORT_SYMBOL(isac_irq
);
893 module_init(hisax_isac_init
);
894 module_exit(hisax_isac_exit
);