File: /usr/src/linux/drivers/isdn/hisax/arcofi.c

1     /* $Id: arcofi.c,v 1.12.6.1 2001/02/16 16:43:25 kai Exp $
2      *
3      * arcofi.c   Ansteuerung ARCOFI 2165
4      *
5      * Author     Karsten Keil (keil@isdn4linux.de)
6      *
7      * This file is (c) under GNU General Public License
8      *
9      */
10      
11     #define __NO_VERSION__
12     #include "hisax.h"
13     #include "isdnl1.h"
14     #include "isac.h"
15     #include "arcofi.h"
16     
17     #define ARCOFI_TIMER_VALUE	20
18     
19     static void
20     add_arcofi_timer(struct IsdnCardState *cs) {
21     	if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
22     		del_timer(&cs->dc.isac.arcofitimer);
23     	}	
24     	init_timer(&cs->dc.isac.arcofitimer);
25     	cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ)/1000);
26     	add_timer(&cs->dc.isac.arcofitimer);
27     }
28     
29     static void
30     send_arcofi(struct IsdnCardState *cs) {
31     	u_char val;
32     	
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     	val = 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     }
134