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