]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blob - drivers/isdn/hisax/arcofi.c
Linux-2.6.12-rc2
[mirror_ubuntu-eoan-kernel.git] / drivers / isdn / hisax / arcofi.c
1 /* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $
2 *
3 * Ansteuerung ARCOFI 2165
4 *
5 * Author Karsten Keil
6 * Copyright by Karsten Keil <keil@isdn4linux.de>
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12
13 #include "hisax.h"
14 #include "isdnl1.h"
15 #include "isac.h"
16 #include "arcofi.h"
17
18 #define ARCOFI_TIMER_VALUE 20
19
20 static void
21 add_arcofi_timer(struct IsdnCardState *cs) {
22 if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
23 del_timer(&cs->dc.isac.arcofitimer);
24 }
25 init_timer(&cs->dc.isac.arcofitimer);
26 cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
27 add_timer(&cs->dc.isac.arcofitimer);
28 }
29
30 static void
31 send_arcofi(struct IsdnCardState *cs) {
32 u_char val;
33
34 add_arcofi_timer(cs);
35 cs->dc.isac.mon_txp = 0;
36 cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
37 memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
38 switch(cs->dc.isac.arcofi_bc) {
39 case 0: break;
40 case 1: cs->dc.isac.mon_tx[1] |= 0x40;
41 break;
42 default: break;
43 }
44 cs->dc.isac.mocr &= 0x0f;
45 cs->dc.isac.mocr |= 0xa0;
46 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
47 val = cs->readisac(cs, ISAC_MOSR);
48 cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
49 cs->dc.isac.mocr |= 0x10;
50 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
51 }
52
53 int
54 arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
55 if (cs->debug & L1_DEB_MONITOR) {
56 debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
57 }
58 if (event == ARCOFI_TIMEOUT) {
59 cs->dc.isac.arcofi_state = ARCOFI_NOP;
60 test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
61 wake_up(&cs->dc.isac.arcofi_wait);
62 return(1);
63 }
64 switch (cs->dc.isac.arcofi_state) {
65 case ARCOFI_NOP:
66 if (event == ARCOFI_START) {
67 cs->dc.isac.arcofi_list = data;
68 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
69 send_arcofi(cs);
70 }
71 break;
72 case ARCOFI_TRANSMIT:
73 if (event == ARCOFI_TX_END) {
74 if (cs->dc.isac.arcofi_list->receive) {
75 add_arcofi_timer(cs);
76 cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
77 } else {
78 if (cs->dc.isac.arcofi_list->next) {
79 cs->dc.isac.arcofi_list =
80 cs->dc.isac.arcofi_list->next;
81 send_arcofi(cs);
82 } else {
83 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
84 del_timer(&cs->dc.isac.arcofitimer);
85 }
86 cs->dc.isac.arcofi_state = ARCOFI_NOP;
87 wake_up(&cs->dc.isac.arcofi_wait);
88 }
89 }
90 }
91 break;
92 case ARCOFI_RECEIVE:
93 if (event == ARCOFI_RX_END) {
94 if (cs->dc.isac.arcofi_list->next) {
95 cs->dc.isac.arcofi_list =
96 cs->dc.isac.arcofi_list->next;
97 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
98 send_arcofi(cs);
99 } else {
100 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
101 del_timer(&cs->dc.isac.arcofitimer);
102 }
103 cs->dc.isac.arcofi_state = ARCOFI_NOP;
104 wake_up(&cs->dc.isac.arcofi_wait);
105 }
106 }
107 break;
108 default:
109 debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
110 return(2);
111 }
112 return(0);
113 }
114
115 static void
116 arcofi_timer(struct IsdnCardState *cs) {
117 arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
118 }
119
120 void
121 clear_arcofi(struct IsdnCardState *cs) {
122 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
123 del_timer(&cs->dc.isac.arcofitimer);
124 }
125 }
126
127 void
128 init_arcofi(struct IsdnCardState *cs) {
129 cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
130 cs->dc.isac.arcofitimer.data = (long) cs;
131 init_timer(&cs->dc.isac.arcofitimer);
132 init_waitqueue_head(&cs->dc.isac.arcofi_wait);
133 test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
134 }