• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/isdn/hisax/
1/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 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
21static void
22add_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
31static void
32send_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
54int
55arcofi_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
116static void
117arcofi_timer(struct IsdnCardState *cs) {
118	arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
119}
120
121void
122clear_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
128void
129init_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