Merge branch 'master' of git://git.kernel.org/pub/scm/fs/xfs/xfs
[linux-2.6] / 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 }