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 	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
arcofi_fsm(struct IsdnCardState * cs,int event,void * data)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
arcofi_timer(struct IsdnCardState * cs)115 arcofi_timer(struct IsdnCardState *cs) {
116 	arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
117 }
118 
119 void
clear_arcofi(struct IsdnCardState * cs)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
init_arcofi(struct IsdnCardState * cs)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 }
134