blob: 2f784f96d439c580719897cedf14da4a91e76cb9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $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 */
Joe Perches475be4d2012-02-19 19:52:38 -080012
Alexey Dobriyand43c36d2009-10-07 17:09:06 +040013#include <linux/sched.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#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);
Joe Perches475be4d2012-02-19 19:52:38 -080025 }
Joe Perches475be4d2012-02-19 19:52:38 -080026 cs->dc.isac.arcofitimer.expires = jiffies + ((ARCOFI_TIMER_VALUE * HZ) / 1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -070027 add_timer(&cs->dc.isac.arcofitimer);
28}
29
30static void
31send_arcofi(struct IsdnCardState *cs) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070032 add_arcofi_timer(cs);
33 cs->dc.isac.mon_txp = 0;
34 cs->dc.isac.mon_txc = cs->dc.isac.arcofi_list->len;
35 memcpy(cs->dc.isac.mon_tx, cs->dc.isac.arcofi_list->msg, cs->dc.isac.mon_txc);
Joe Perches475be4d2012-02-19 19:52:38 -080036 switch (cs->dc.isac.arcofi_bc) {
37 case 0: break;
38 case 1: cs->dc.isac.mon_tx[1] |= 0x40;
39 break;
40 default: break;
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 }
42 cs->dc.isac.mocr &= 0x0f;
43 cs->dc.isac.mocr |= 0xa0;
44 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
David S. Miller011bc1e2011-04-17 16:36:28 -070045 (void) cs->readisac(cs, ISAC_MOSR);
Linus Torvalds1da177e2005-04-16 15:20:36 -070046 cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]);
47 cs->dc.isac.mocr |= 0x10;
48 cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr);
49}
50
51int
52arcofi_fsm(struct IsdnCardState *cs, int event, void *data) {
53 if (cs->debug & L1_DEB_MONITOR) {
54 debugl1(cs, "arcofi state %d event %d", cs->dc.isac.arcofi_state, event);
55 }
56 if (event == ARCOFI_TIMEOUT) {
57 cs->dc.isac.arcofi_state = ARCOFI_NOP;
58 test_and_set_bit(FLG_ARCOFI_ERROR, &cs->HW_Flags);
59 wake_up(&cs->dc.isac.arcofi_wait);
Joe Perches475be4d2012-02-19 19:52:38 -080060 return (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061 }
62 switch (cs->dc.isac.arcofi_state) {
Joe Perches475be4d2012-02-19 19:52:38 -080063 case ARCOFI_NOP:
64 if (event == ARCOFI_START) {
65 cs->dc.isac.arcofi_list = data;
66 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
67 send_arcofi(cs);
68 }
69 break;
70 case ARCOFI_TRANSMIT:
71 if (event == ARCOFI_TX_END) {
72 if (cs->dc.isac.arcofi_list->receive) {
73 add_arcofi_timer(cs);
74 cs->dc.isac.arcofi_state = ARCOFI_RECEIVE;
75 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 if (cs->dc.isac.arcofi_list->next) {
77 cs->dc.isac.arcofi_list =
78 cs->dc.isac.arcofi_list->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 send_arcofi(cs);
80 } else {
81 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
82 del_timer(&cs->dc.isac.arcofitimer);
83 }
84 cs->dc.isac.arcofi_state = ARCOFI_NOP;
85 wake_up(&cs->dc.isac.arcofi_wait);
86 }
87 }
Joe Perches475be4d2012-02-19 19:52:38 -080088 }
89 break;
90 case ARCOFI_RECEIVE:
91 if (event == ARCOFI_RX_END) {
92 if (cs->dc.isac.arcofi_list->next) {
93 cs->dc.isac.arcofi_list =
94 cs->dc.isac.arcofi_list->next;
95 cs->dc.isac.arcofi_state = ARCOFI_TRANSMIT;
96 send_arcofi(cs);
97 } else {
98 if (test_and_clear_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) {
99 del_timer(&cs->dc.isac.arcofitimer);
100 }
101 cs->dc.isac.arcofi_state = ARCOFI_NOP;
102 wake_up(&cs->dc.isac.arcofi_wait);
103 }
104 }
105 break;
106 default:
107 debugl1(cs, "Arcofi unknown state %x", cs->dc.isac.arcofi_state);
108 return (2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 }
Joe Perches475be4d2012-02-19 19:52:38 -0800110 return (0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111}
112
113static void
Kees Cook5e8b8242017-10-16 17:28:54 -0700114arcofi_timer(struct timer_list *t) {
115 struct IsdnCardState *cs = from_timer(cs, t, dc.isac.arcofitimer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 arcofi_fsm(cs, ARCOFI_TIMEOUT, NULL);
117}
118
119void
120clear_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
126void
127init_arcofi(struct IsdnCardState *cs) {
Kees Cook5e8b8242017-10-16 17:28:54 -0700128 timer_setup(&cs->dc.isac.arcofitimer, arcofi_timer, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 init_waitqueue_head(&cs->dc.isac.arcofi_wait);
130 test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
131}