Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / 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 <linux/sched.h>
14 #include "hisax.h"
15 #include "isdnl1.h"
16 #include "isac.h"
17 #include "arcofi.h"
18
19 #define ARCOFI_TIMER_VALUE      20
20
21 static void
22 add_arcofi_timer(struct IsdnCardState *cs) {
23         if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
24                 del_timer(&cs->dc.isac.arcofitimer);
25         }
26         init_timer(&cs->dc.isac.arcofitimer);
27         cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ) / 1000);
28         add_timer(&cs->dc.isac.arcofitimer);
29 }
30
31 static void
32 send_arcofi(struct IsdnCardState *cs) {
33         add_arcofi_timer(cs);
34         cs->dc.isac.mon_txp = 0;
35         cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
36         memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
37         switch (cs->dc.isac.arcofi_bc) {
38         case 0: break;
39         case 1: cs->dc.isac.mon_tx[1] |= 0x40;
40                 break;
41         default: break;
42         }
43         cs->dc.isac.mocr &= 0x0f;
44         cs->dc.isac.mocr |= 0xa0;
45         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
46         (void) cs->readisac(cs, ISAC_MOSR);
47         cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
48         cs->dc.isac.mocr |= 0x10;
49         cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
50 }
51
52 int
53 arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
54         if (cs->debug & L1_DEB_MONITOR) {
55                 debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
56         }
57         if (event == ARCOFI_TIMEOUT) {
58                 cs->dc.isac.arcofi_state = ARCOFI_NOP;
59                 test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
60                 wake_up(&cs->dc.isac.arcofi_wait);
61                 return (1);
62         }
63         switch (cs->dc.isac.arcofi_state) {
64         case ARCOFI_NOP:
65                 if (event == ARCOFI_START) {
66                         cs->dc.isac.arcofi_list = data;
67                         cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
68                         send_arcofi(cs);
69                 }
70                 break;
71         case ARCOFI_TRANSMIT:
72                 if (event == ARCOFI_TX_END) {
73                         if (cs->dc.isac.arcofi_list->receive) {
74                                 add_arcofi_timer(cs);
75                                 cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
76                         } else {
77                                 if (cs->dc.isac.arcofi_list->next) {
78                                         cs->dc.isac.arcofi_list =
79                                                 cs->dc.isac.arcofi_list->next;
80                                         send_arcofi(cs);
81                                 } else {
82                                         if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
83                                                 del_timer(&cs->dc.isac.arcofitimer);
84                                         }
85                                         cs->dc.isac.arcofi_state = ARCOFI_NOP;
86                                         wake_up(&cs->dc.isac.arcofi_wait);
87                                 }
88                         }
89                 }
90                 break;
91         case ARCOFI_RECEIVE:
92                 if (event == ARCOFI_RX_END) {
93                         if (cs->dc.isac.arcofi_list->next) {
94                                 cs->dc.isac.arcofi_list =
95                                         cs->dc.isac.arcofi_list->next;
96                                 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
97                                 send_arcofi(cs);
98                         } else {
99                                 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
100                                         del_timer(&cs->dc.isac.arcofitimer);
101                                 }
102                                 cs->dc.isac.arcofi_state = ARCOFI_NOP;
103                                 wake_up(&cs->dc.isac.arcofi_wait);
104                         }
105                 }
106                 break;
107         default:
108                 debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
109                 return (2);
110         }
111         return (0);
112 }
113
114 static void
115 arcofi_timer(struct IsdnCardState *cs) {
116         arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
117 }
118
119 void
120 clear_arcofi(struct IsdnCardState *cs) {
121         if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
122                 del_timer(&cs->dc.isac.arcofitimer);
123         }
124 }
125
126 void
127 init_arcofi(struct IsdnCardState *cs) {
128         cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
129         cs->dc.isac.arcofitimer.data = (long) cs;
130         init_timer(&cs->dc.isac.arcofitimer);
131         init_waitqueue_head(&cs->dc.isac.arcofi_wait);
132         test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
133 }